Skip to Content
architectureredisjavasecurity

Distributed Session Management at Risk-Scale

AUTHENTICATED_ACCESS_GRANTED

The Context: "The 3 AM Trigger"

It was Halloween night, October 2023. Our client, "SecureNet HR" (name changed), managed payroll services. They were migrating from a sticky-session monolith to a stateless, containerized Spring Boot microservice cluster. They decided to drop server-side sessions entirely and issue 24-hour JSON Web Tokens (JWTs) stored in client-side cookies. At 3 AM, a massive credential stuffing attack successfully compromised 5,000 employee accounts. The CISO ordered an immediate global session invalidation. The engineers suddenly realized a horrifying truth: because the JWTs were entirely stateless and verified cryptographically offline by the services, there was no centralized server state to invalidate. The tokens were valid for 24 hours, and we couldn't stop the attackers without literally rotating the global RSA signing keys, logging out all 3 million valid users in the process. Total baigan security posture. We needed a hybrid session architecture.

The Problem Statement

Our constraints for the new session architecture:

  • Stateless Validation: The downstream microservices must still validate requests in under 1ms without querying a database.
  • Immediate Revocation: The security team must be able to instantly revoke a specific user's session globally.
  • Scale: Must support 50,000 login/logout/refresh events per second.
  • Data Footprint: Keep the centralized session state incredibly small.

Visual Architecture

The Core Logic / Process

Data Flow

We implemented a "Short-Lived JWT + Redis Blacklist" pattern (often known as a Deny-List). When a user logs in, the Auth Server issues an Access Token (JWT) with a short 15-minute lifespan and a unique jti (JWT ID) claim. It also issues an opaque Refresh Token tied to a standard session row in the Oracle DB.

When the client makes a request, the API Gateway cryptographically verifies the JWT signature offline. This takes microseconds. Then, the Gateway parses the jti claim and fires a sub-millisecond query to a highly-available Redis cluster: EXISTS blacklist:<jti>. Since 99.99% of tokens are valid, this almost always returns false, and the request passes to the microservices.

Concurrency & Locking

If the CISO clicks "Revoke Session", the Auth Server immediately writes the user's current jti into the Redis Blacklist with a TTL matching the remainder of the token's 15-minute lifespan. The very next request the attacker makes hits the Gateway, the Redis EXISTS check returns true, and the Gateway throws a 401 Unauthorized. Because the Redis inserts only require a TTL and no complex data structures, locking is irrelevant. Redis handles 100k EXISTS checks per second effortlessly on a single core.

Failure Modes

What happens if the Redis Blacklist goes down? We "Fail Open". If the Spring Gateway cannot reach Redis within 3ms, it assumes the token is valid (provided the cryptographic signature holds). The worst-case scenario is that a theoretically revoked token remains usable for a maximum of 14 minutes and 59 seconds until it natively expires. For a payroll system, a 15-minute exposure window during a catastrophic internal Redis failure was deemed an acceptable business risk versus bringing down the entire platform.

The "Baigan" Take (Expert Insights)

Look, everyone reads blog posts saying "JWTs are stateless, you don't need a database!" That is fundamentally untrue the second you have a compliance requirement for instant session termination.

We initially tried to store a global user_version number in the JWT and mirror it in Redis, invalidating tokens if the numbers didn't match. This created a massive memory footprint because we had to store 3 million active version numbers in Redis. By switching to a purely JTI Blacklist, we only store the revoked tokens in RAM. Out of 3 million users, maybe 1,000 are actively revoked at any given time. Our Redis memory footprint dropped from 12GB to under 15MB.

Performance Checklist

  • Limit Access Token JWT lifespans to 15 minutes or less to cap maximum exposure windows.
  • Implement a jti (JWT ID) Deny-List in Redis at the API Gateway layer.
  • Assign a Redis TTL to the jti blacklist entry equal to the remaining lifespan of the JWT.
  • Ensure your Gateway Redis client fails-open quickly (e.g., 3-5ms timeout) to prevent cascading outages.
© 2026 PRANABESH_VAULT_ENCRYPTION_V4CONFIDENTIAL_REPRODUCTION_PROHIBITED