Session Storage with Arctickey

Redis is the go-to solution for session storage. Fast, reliable, and works across multiple servers.

Why Redis for Sessions?#

  • Shared state — sessions work across all app servers
  • Fast lookups — sub-millisecond session retrieval
  • Auto-expiration — sessions expire automatically
  • Scalable — handles millions of sessions

Express.js Sessions#

Terminal
npm install express-session connect-redis ioredis
TypeScript
import express from 'express'; import session from 'express-session'; import RedisStore from 'connect-redis'; import Redis from 'ioredis'; const app = express(); const redis = new Redis('rediss://:YOUR_PASSWORD@YOUR_INSTANCE.eu.arctickey.com:6379'); app.use(session({ store: new RedisStore({ client: redis }), secret: 'your-secret-key', resave: false, saveUninitialized: false, cookie: { secure: true, // HTTPS only httpOnly: true, // No JS access maxAge: 86400000, // 24 hours }, })); // Use sessions app.get('/login', (req, res) => { req.session.userId = '123'; req.session.role = 'admin'; res.send('Logged in'); }); app.get('/profile', (req, res) => { if (!req.session.userId) { return res.status(401).send('Not authenticated'); } res.json({ userId: req.session.userId }); });

Next.js (NextAuth.js)#

Terminal
npm install next-auth @auth/drizzle-adapter ioredis
TypeScript
// lib/redis.ts import Redis from 'ioredis'; export const redis = new Redis('rediss://:YOUR_PASSWORD@YOUR_INSTANCE.eu.arctickey.com:6379'); // Custom session store for NextAuth export const redisSessionStore = { async get(sessionId: string) { const data = await redis.get(`session:${sessionId}`); return data ? JSON.parse(data) : null; }, async set(sessionId: string, data: any, maxAge: number) { await redis.setex(`session:${sessionId}`, maxAge, JSON.stringify(data)); }, async delete(sessionId: string) { await redis.del(`session:${sessionId}`); }, };

Laravel Sessions#

PHP
// .env SESSION_DRIVER=redis REDIS_URL=rediss://:YOUR_PASSWORD@YOUR_INSTANCE.eu.arctickey.com:6379 // config/session.php 'driver' => env('SESSION_DRIVER', 'redis'), 'lifetime' => 120, // minutes 'connection' => 'default',

Django Sessions#

Python
# settings.py CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'rediss://:YOUR_PASSWORD@YOUR_INSTANCE.eu.arctickey.com:6379/1', 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', 'CONNECTION_POOL_KWARGS': {'ssl_cert_reqs': None}, } } } SESSION_ENGINE = 'django.contrib.sessions.backends.cache' SESSION_CACHE_ALIAS = 'default'

Ruby on Rails#

Ruby
# config/initializers/session_store.rb Rails.application.config.session_store :redis_store, servers: ['rediss://:YOUR_PASSWORD@YOUR_INSTANCE.eu.arctickey.com:6379/0/sessions'], expire_after: 24.hours, key: '_myapp_session', ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }

Manual Session Management#

For custom implementations:

TypeScript
import Redis from 'ioredis'; import { nanoid } from 'nanoid'; const redis = new Redis('rediss://:YOUR_PASSWORD@YOUR_INSTANCE.eu.arctickey.com:6379'); const SESSION_TTL = 86400; // 24 hours // Create session async function createSession(userId: string, data: object) { const sessionId = nanoid(32); const session = { userId, ...data, createdAt: Date.now() }; await redis.setex( `session:${sessionId}`, SESSION_TTL, JSON.stringify(session) ); // Track user's sessions await redis.sadd(`user:${userId}:sessions`, sessionId); return sessionId; } // Get session async function getSession(sessionId: string) { const data = await redis.get(`session:${sessionId}`); if (!data) return null; // Refresh TTL on access (sliding expiration) await redis.expire(`session:${sessionId}`, SESSION_TTL); return JSON.parse(data); } // Destroy session async function destroySession(sessionId: string) { const session = await getSession(sessionId); if (session?.userId) { await redis.srem(`user:${session.userId}:sessions`, sessionId); } await redis.del(`session:${sessionId}`); } // Destroy all user sessions (logout everywhere) async function destroyAllUserSessions(userId: string) { const sessions = await redis.smembers(`user:${userId}:sessions`); if (sessions.length > 0) { await redis.del(...sessions.map(s => `session:${s}`)); await redis.del(`user:${userId}:sessions`); } }

Security Best Practices#

  1. Use secure cookiessecure: true, httpOnly: true
  2. Rotate session IDs after authentication
  3. Set reasonable TTLs — 24 hours for web, shorter for sensitive apps
  4. Implement logout — actually delete the session
  5. Monitor for abuse — rate limit session creation
  6. Store minimal data — just user ID and role, not sensitive info

Session Key Naming#

TEXT
session:{sessionId} # Session data user:{userId}:sessions # Set of user's active sessions session:{sessionId}:csrf # CSRF tokens