Using MemoryStore in production

node.js

node.js Problem Overview


Today I ran my Node.js application in "production" mode for the first time and got this warning:

Warning: connection.session() MemoryStore is not
designed for a production environment, as it will leak
memory, and obviously only work within a single process.

I only need to run a single process, but what should I use instead? I want my sessions to reside in RAM for fast access. I also want to be able to discard all the sessions by simply shutting down the Node app.

It seems an overkill to install Redis, MongoDB or another database just for this simple task. I also don't understand why is MemoryStore included in Node when it should not really be used?

node.js Solutions


Solution 1 - node.js

Ok, after talking to Connect developers, I got more information. There are two things considered memory leaks here:

  1. problem with JSON parsing which is already fixed in recent versions
  2. the fact that there is no cleanup of expired sessions if the users never access them (i.e. the only cleanup is on-access)

The solution seems to be rather simple, at least this is what I plan to do: use setInterval to periodically clean up the expired sessions. MemoryStore provides all() to get the list, and we can use get() to force reading and thus expire them. Pseudo-code:

function sessionCleanup() {
    sessionStore.all(function(err, sessions) {
        for (var i = 0; i < sessions.length; i++) {
            sessionStore.get(sessions[i], function() {} );
        }
    });
}

Now just call sessionCleanup periodically via setInterval() and you have automatic garbage collection for expired sessions. No more memory leaks.

Solution 2 - node.js

So the accepted answer to this is [edit: was] pretty much a hack, and the others are just recommending using a database which I think is overkill.

I had the same problem and just replaced express-session with cookie-session.

To do this simply install cookie-session:

npm install cookie-session

Then in your app.js, find where express-session is being used and replace with cookie-session.

app.use(require('cookie-session')({
    // Cookie config, take a look at the docs...
}));

You may need to change some other things, for me is was a simple swap-out-bobs-your-uncle-no-harm-done.

Solution 3 - node.js

MemoryStore is just for (rapid) development mode, because if your app restarts (process dies) you will lose all the session data (that resided in the memory of that process).

If you don't want to use a database, use encrypted cookie storage instead.

http://www.senchalabs.org/connect/cookieSession.html

Solution 4 - node.js

This module was designed to deal with the memory leak issue. https://www.npmjs.com/package/session-memory-store

The accepted answer may be fine. However, since this question shows up high in the list of search results I figured I would include this in case it helps anyone else.

Solution 5 - node.js

I think the consensus around the web is that the right way would be to indeed use a DB for that, but if you're positive you don't want to do that, then suppress the warning -- the warning is not law.

However, since you and I both agree that the memory leak is a real problem, it is hard to justify saying redis is overkill, since it would solve your problem.

> I also don't understand why is MemoryStore included in Node when it > should not really be used

that is a great point -- but to that I would say that node iself has only recently itself become production ready. Some people would not agree with the notion that it is at all.

Solution 6 - node.js

The alternative is to use Redis or Mongo as a store. With Mongo you use the express-session-mongo module.

There is an advice to remove stale sessions with an indexing option:

var MongoStore = require('express-session-mongo');
app.use(express.session({ store: new MongoStore() }));

db.sessions.ensureIndex( { "lastAccess": 1 }, { expireAfterSeconds: 3600 } )

Since stale sessions are removed by the database itself, Express session doesn't need to handle the cleanup by itself.

EDIT: It seems like you need to have your own "lastAccess" field. When you access it you update that field yourself. Check the MongoDB documentation expire-data http://docs.mongodb.org/manual/tutorial/expire-data/

EDIT2:

Now becomes db.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

The Mongo background thread to check this field runs every 60 seconds. So the timing to remove the document is not exact.

Solution 7 - node.js

For those who are having trouble with Redis try the following - hope this helps.

I'm using Redis for DEV and PROD and targeting Express v4. On Windows I'm using the lightweight MSOpenTech Redis v3.0 toolset, otherwise, I just use the Heroku Redis Addon. To get it to work via Node hasn't been too hard - so far...

var session = require('express-session');

. . .

var RedisStore = require('connect-redis')(session);

var redisClient = require('redis').createClient(process.env.REDIS_URL);

var redisOptions = { 
    	client: redisClient, 
	    no_ready_check: true,
		ttl: 600,
    	logErrors: true
};

var redisSessionStore = new RedisStore(redisOptions);

app.use(session({
    store: redisSessionStore,
    secret: 'Some.Long.Series.of.Crazy.Words.and.Jumbled.letter.etc',
	resave: true,		
	saveUninitialized: true	
}));

Good luck!

ps. I only just re-read the original query and noticed this - sorry!

> It seems an overkill to install Redis, MongoDB or another database just for this simple task.

Solution 8 - node.js

If you use OSX use

brew install memcached

if linux

apt install memcached

solve session message, becose de app can connect to 127.0.0.1:11211 memcache service.

Solution 9 - node.js

Use

import createMemoryStore from "memorystore";
...
// Memory store
const MemoryStore = createMemoryStore(session);
app.use(session({
    ...
    store: new MemoryStore({
        checkPeriod: 86400000 // prune expired entries every 24h
    }),
    ...
}))

Fix the problem in my case

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMilan BabuškovView Question on Stackoverflow
Solution 1 - node.jsMilan BabuškovView Answer on Stackoverflow
Solution 2 - node.jsigneosaurView Answer on Stackoverflow
Solution 3 - node.jsalessioalexView Answer on Stackoverflow
Solution 4 - node.jsDovev HefetzView Answer on Stackoverflow
Solution 5 - node.jsKristianView Answer on Stackoverflow
Solution 6 - node.jshuggieView Answer on Stackoverflow
Solution 7 - node.jsGarry MayView Answer on Stackoverflow
Solution 8 - node.jsAnthonyView Answer on Stackoverflow
Solution 9 - node.jsuser16125753View Answer on Stackoverflow