Storing Sessions in Redis with Express
The default in-memory session store loses every session on restart and doesn't work with more than one server. Redis is the standard fix: fast, shared and with built-in expiry.
Setup
npm install express-session connect-redis redis
import express from 'express';
import session from 'express-session';
import { RedisStore } from 'connect-redis';
import { createClient } from 'redis';
const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();
const app = express();
app.set('trust proxy', 1); // behind a load balancer that terminates HTTPS
app.use(session({
store: new RedisStore({ client: redis, prefix: 'sess:' }),
secret: process.env.SESSION_SECRET,
name: 'sid',
resave: false,
saveUninitialized: false,
rolling: true, // extend expiry on activity
cookie: {
httpOnly: true, // not readable from JavaScript
secure: true, // HTTPS only
sameSite: 'lax', // CSRF protection for most cases
maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days
},
}));
Signing in and out
app.post('/login', async (req, res, next) => {
const user = await verifyCredentials(req.body.email, req.body.password);
if (!user) return res.status(401).json({ error: 'Invalid email or password' });
req.session.regenerate((err) => { // new session id: prevents session fixation
if (err) return next(err);
req.session.userId = user.id;
res.json({ ok: true });
});
});
app.post('/logout', (req, res) => {
req.session.destroy(() => {
res.clearCookie('sid');
res.json({ ok: true });
});
});
Why this design works
- The cookie only holds a random session ID; user data stays on the server.
- Redis TTLs expire old sessions automatically.
- "Sign out everywhere" is easy: delete the user's session keys.
Store minimal data in the session (a user ID and a few flags), and look up everything else from the database or cache.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.