# User Session Management Low-Level Design

Source: https://www.techinterview.org/post/3233467927/lld-user-session/
Updated: 2026-04-17 · techinterview.org

## User Session Management — Low-Level Design

A session management system authenticates users and maintains their login state across requests. It must handle session creation, validation, expiry, revocation, and multi-device management. This is asked at nearly every company — it underpins every authenticated product.

## Core Data Model


```
Session
  id              TEXT PK            -- random 32-byte hex token
  user_id         BIGINT NOT NULL
  created_at      TIMESTAMPTZ NOT NULL
  expires_at      TIMESTAMPTZ NOT NULL
  last_active_at  TIMESTAMPTZ NOT NULL
  ip_address      INET
  user_agent      TEXT
  device_id       TEXT               -- stable per-device identifier
  revoked_at      TIMESTAMPTZ        -- null = active

-- Index for fast per-user session listing (account management page)
CREATE INDEX idx_sessions_user ON Session(user_id, created_at DESC)
  WHERE revoked_at IS NULL;
```


## Session Creation on Login


```
import secrets

def create_session(user_id, ip_address, user_agent):
    # Cryptographically secure random token — not a UUID
    token = secrets.token_hex(32)  # 64-character hex string, 256 bits of entropy

    db.execute("""
        INSERT INTO Session
          (id, user_id, created_at, expires_at, last_active_at, ip_address, user_agent)
        VALUES
          (%(token)s, %(uid)s, NOW(), NOW() + INTERVAL '30 days',
           NOW(), %(ip)s, %(ua)s)
    """, {'token': token, 'uid': user_id, 'ip': ip_address, 'ua': user_agent})

    # Cache in Redis for fast validation (avoid DB hit on every request)
    redis.setex(f'session:{token}', 3600, json.dumps({
        'user_id': user_id,
        'expires_at': (now() + timedelta(days=30)).isoformat()
    }))

    return token
```


## Session Validation on Each Request


```
def validate_session(token):
    # 1. Check Redis cache first
    cached = redis.get(f'session:{token}')
    if cached:
        data = json.loads(cached)
        if data['expires_at'] > now().isoformat():
            # Extend Redis TTL on activity (sliding window)
            redis.expire(f'session:{token}', 3600)
            return data['user_id']

    # 2. Cache miss or expired — check DB
    session = db.execute("""
        SELECT user_id, expires_at, revoked_at
        FROM Session
        WHERE id = %(token)s
    """, {'token': token}).first()

    if not session:
        raise InvalidSession('Session not found')
    if session.revoked_at is not None:
        raise InvalidSession('Session revoked')
    if session.expires_at < now():
        raise InvalidSession('Session expired')

    # Refresh cache
    redis.setex(f'session:{token}', 3600, json.dumps({
        'user_id': session.user_id,
        'expires_at': session.expires_at.isoformat()
    }))

    # Update last_active_at asynchronously (avoid write on every request)
    update_last_active_async(token)

    return session.user_id
```


## Session Revocation


```
def revoke_session(token):
    """Logout: revoke a single session."""
    db.execute("""
        UPDATE Session SET revoked_at=NOW()
        WHERE id=%(token)s AND revoked_at IS NULL
    """, {'token': token})
    redis.delete(f'session:{token}')  # Immediate cache invalidation

def revoke_all_sessions(user_id, except_token=None):
    """Logout all devices."""
    db.execute("""
        UPDATE Session SET revoked_at=NOW()
        WHERE user_id=%(uid)s
          AND revoked_at IS NULL
          AND (%(except)s IS NULL OR id != %(except)s)
    """, {'uid': user_id, 'except': except_token})

    # Cannot efficiently invalidate all user's Redis keys without a user→sessions index
    # Option 1: store session IDs in a Redis set per user
    session_ids = redis.smembers(f'user_sessions:{user_id}')
    for sid in session_ids:
        redis.delete(f'session:{sid}')
    redis.delete(f'user_sessions:{user_id}')
```


## JWT vs Opaque Tokens


```
Opaque tokens (recommended for most applications):
  + Revocation is immediate: delete from Redis/DB
  + No sensitive data in the token
  + Token size: 64 chars
  - Requires server-side lookup on every request

JWT (stateless tokens):
  + No server-side storage needed; validated by signature alone
  + Works well for microservices (no shared session store)
  - Revocation is hard: token is valid until expiry unless you maintain a denylist
    (which defeats the stateless benefit)
  - Access token expiry must be short (15 min) → requires refresh token flow
  - Sensitive data can be read if not encrypted (JWE vs JWS)

Use JWT for: short-lived API access tokens, service-to-service auth
Use opaque tokens for: user sessions where logout must be instant
```


## Key Interview Points

- **Use secrets.token_hex(32), not UUID:** UUID v4 has only 122 bits of entropy and is not designed for security tokens. A 32-byte random hex string from a CSPRNG has 256 bits — brute-force infeasible.

- **Redis TTL shorter than DB expiry:** Redis TTL of 1 hour with DB expiry of 30 days provides fast validation on active sessions while ensuring inactive sessions expire from the cache automatically.

- **Async last_active_at update:** Writing last_active_at on every authenticated request doubles your write load. Buffer updates and flush every 60 seconds, or use a sliding window with Redis EXPIRE.

- **Revocation requires cache invalidation:** DELETE from Redis on logout. Without this, a revoked session remains valid in the cache for up to 1 hour — unacceptable for security-sensitive logout scenarios.

User session management and authentication design is discussed in [Google system design interview questions](https://www.techinterview.org/post/3233460274/netflix-interview-guide-2026-streaming-architecture-recommendation-systems-and-engineering-excellence/).

Session management and login system design is covered in [Meta system design interview preparation](https://www.techinterview.org/post/3233460272/meta-interview-guide-2026-facebook-instagram-whatsapp-engineering/).

User session and multi-device authentication design is discussed in [Netflix system design interview guide](https://www.techinterview.org/?p=3233460282).
