DEV Community

Cover image for Authentication at Scale: Sessions, JWT, Tokens, OAuth & Distributed Auth
Tanu Priya
Tanu Priya

Posted on

Authentication at Scale: Sessions, JWT, Tokens, OAuth & Distributed Auth

Authentication looks simple when an application has a few users.

A user enters an email and password, the server verifies the credentials, and the user is logged in.

But what happens when your application has millions of users, thousands of requests per second, multiple servers, mobile apps, and services distributed across different regions?

Authentication becomes a system-design problem.

You need to answer questions like:

  • Where should authentication state be stored?
  • How do multiple servers know that a user is logged in?
  • Should you use sessions or JWTs?
  • How should tokens expire?
  • How do you revoke access?
  • How does OAuth work?
  • How do microservices verify users?
  • How do you scale authentication across regions?

Let's break it down.


What Is Authentication?

Authentication answers one fundamental question:

"Who are you?"

For example:

User
  ↓
Email + Password
  ↓
Authentication Server
  ↓
Identity Verified
  ↓
Authenticated User
Enter fullscreen mode Exit fullscreen mode

Authentication is different from authorization.

Authentication

Determines who the user is.

Who are you?
→ User 123
Enter fullscreen mode Exit fullscreen mode

Authorization

Determines what the user is allowed to do.

What can User 123 access?
→ Read orders
→ Create orders
→ Cannot access admin panel
Enter fullscreen mode Exit fullscreen mode

A scalable system usually needs both.


Basic Authentication Flow

A simple login system might work like this:

User
  │
  │ Email + Password
  ▼
Auth Server
  │
  │ Verify Credentials
  ▼
User Database
  │
  │ Valid
  ▼
Session / Token
  │
  ▼
User
Enter fullscreen mode Exit fullscreen mode

After login, the client needs some way to prove its identity on future requests.

This is where sessions and tokens come in.


Session-Based Authentication

With session-based authentication, the server creates a session after successful login.

For example:

User
  ↓
Login
  ↓
Server
  ↓
Create Session
  ↓
Session ID
  ↓
Browser Cookie
Enter fullscreen mode Exit fullscreen mode

The browser might store:

session_id=abc123
Enter fullscreen mode Exit fullscreen mode

On future requests:

User
  ↓
Cookie: session_id=abc123
  ↓
Server
  ↓
Session Store
  ↓
User Identity
Enter fullscreen mode Exit fullscreen mode

The server uses the session ID to find the user's authentication state.


How Sessions Work at Scale

A single server can store sessions in memory:

User
 ↓
Server
 ↓
RAM
Enter fullscreen mode Exit fullscreen mode

But this creates a problem when multiple servers are introduced.

Imagine:

             Load Balancer
              /        \
             ↓          ↓
        Server 1     Server 2
           │             │
        Session A      Session B
Enter fullscreen mode Exit fullscreen mode

A user logs in through Server 1.

The session exists on Server 1.

The next request might go to Server 2.

Server 2 doesn't know about the session.

This is a problem.


Shared Session Store

One solution is to move sessions into a shared data store.

For example:

                Load Balancer
                /           \
               ▼             ▼
          Server 1       Server 2
               \             /
                \           /
                  ▼       ▼
                Session Store
Enter fullscreen mode Exit fullscreen mode

The session store could be a distributed in-memory database such as Redis.

Now every application server can access the same session state.

Request
   ↓
Any Server
   ↓
Shared Session Store
   ↓
User Session
Enter fullscreen mode Exit fullscreen mode

This makes session-based authentication much easier to scale horizontally.


Advantages of Sessions

Sessions have several useful properties:

  • Easy to invalidate
  • Server controls authentication state
  • Sensitive authentication data doesn't need to be stored directly in the browser
  • Logout can invalidate the session
  • Good fit for traditional web applications

But sessions also have a trade-off:

The server needs to maintain authentication state.

At very large scale, that shared state becomes an important infrastructure component.


What Is a Token?

A token is a piece of data that represents an authenticated identity or authorization.

Instead of storing all authentication state on the server, the client can present a token with its requests.

For example:

User
 ↓
Login
 ↓
Auth Server
 ↓
Access Token
 ↓
Client
Enter fullscreen mode Exit fullscreen mode

Then:

Client
 ↓
Authorization: Bearer <token>
 ↓
API Server
 ↓
Validate Token
 ↓
Request Allowed
Enter fullscreen mode Exit fullscreen mode

Tokens are commonly used in APIs, mobile applications, and distributed systems.


JWT Authentication

One popular token format is JWT (JSON Web Token).

A JWT typically contains information such as:

Header
Payload
Signature
Enter fullscreen mode Exit fullscreen mode

Conceptually:

JWT
 ├── Header
 ├── Payload
 └── Signature
Enter fullscreen mode Exit fullscreen mode

The payload might contain claims such as:

{
  "sub": "user123",
  "role": "user",
  "exp": 1780000000
}
Enter fullscreen mode Exit fullscreen mode

The token is signed so the server can verify that it was issued by a trusted authority and hasn't been modified.


JWT Authentication Flow

A simplified JWT flow looks like this:

User
  ↓
Login
  ↓
Authentication Server
  ↓
JWT
  ↓
Client
  ↓
API Request
  ↓
Authorization: Bearer JWT
  ↓
API Server
  ↓
Verify Signature
  ↓
Allow Request
Enter fullscreen mode Exit fullscreen mode

One major benefit is that the server doesn't necessarily need to look up a session for every request.


Sessions vs JWT

The difference can be summarized like this:

Sessions JWT
Server maintains session state Token carries claims
Session ID sent by client JWT sent by client
Easy revocation Revocation requires additional strategy
Requires shared session storage at scale Can be validated independently
Common for web applications Common for APIs and distributed systems
Server controls session state Client carries the token

Neither is universally better.

The right choice depends on the system.


Stateless Authentication

JWTs are often used to create a more stateless authentication layer.

For example:

                 Load Balancer
                /      |      \
               ▼       ▼       ▼
           Server 1 Server 2 Server 3
              │        │        │
              └──── Verify JWT ─┘
Enter fullscreen mode Exit fullscreen mode

Each server can independently validate the token.

There doesn't necessarily need to be a centralized session lookup for every request.

This can simplify horizontal scaling.

But "stateless" doesn't mean there is no authentication infrastructure.

You still need to manage:

  • Token issuance
  • Signing keys
  • Expiration
  • Refresh tokens
  • Revocation
  • Key rotation
  • User sessions

Access Tokens and Refresh Tokens

A common authentication design uses two types of tokens.

Access Token

Used to access APIs.

Client
 ↓
Access Token
 ↓
API
Enter fullscreen mode Exit fullscreen mode

Access tokens are usually short-lived.

Refresh Token

Used to obtain a new access token.

Refresh Token
      ↓
Authentication Server
      ↓
New Access Token
Enter fullscreen mode Exit fullscreen mode

The flow becomes:

Login
  ↓
Access Token + Refresh Token
  ↓
Client
  │
  ├── Access Token → API
  │
  └── Refresh Token → Auth Server
                           ↓
                    New Access Token
Enter fullscreen mode Exit fullscreen mode

Short-lived access tokens reduce the impact of a stolen token.


Why Not Make Access Tokens Last Forever?

Suppose an access token remains valid for 30 days.

If an attacker obtains it, they may be able to use it for the entire validity period.

Shorter expiration reduces this window.

For example:

Access Token
   ↓
Short Lifetime
   ↓
Expires
   ↓
Refresh Token
   ↓
New Access Token
Enter fullscreen mode Exit fullscreen mode

The exact expiration strategy depends on the application's security and usability requirements.


What Is OAuth?

OAuth is a framework for delegated authorization.

A common example is:

"Continue with Google"

Instead of giving your application your Google password, the user authenticates with Google and grants the application permission to access specific information.

A simplified flow:

User
  ↓
Your Application
  ↓
OAuth Provider
  ↓
User Authentication
  ↓
Authorization
  ↓
Authorization Code
  ↓
Your Backend
  ↓
Access Token
Enter fullscreen mode Exit fullscreen mode

OAuth is especially useful when applications need access to resources controlled by another identity provider.


OAuth vs Authentication

OAuth is primarily about authorization, not simply proving identity.

For user authentication, systems commonly use OpenID Connect (OIDC) on top of OAuth 2.0.

Conceptually:

OAuth
  ↓
Delegated Authorization

OIDC
  ↓
Authentication / Identity
Enter fullscreen mode Exit fullscreen mode

This distinction is important when designing authentication systems.


Authentication in Microservices

Now imagine a system with multiple services:

                API Gateway
                    │
        ┌───────────┼───────────┐
        ▼           ▼           ▼
   User Service Order Service Payment Service
Enter fullscreen mode Exit fullscreen mode

Should every service implement login and password verification?

Usually, no.

A better approach is to centralize identity management.

                 Identity Provider
                       │
                       ▼
                  Access Token
                       │
                       ▼
                  API Gateway
                       │
       ┌───────────────┼───────────────┐
       ▼               ▼               ▼
   User Service    Order Service   Payment Service
Enter fullscreen mode Exit fullscreen mode

Services can validate the authenticated identity and authorization information rather than each implementing its own login system.


Authentication at the API Gateway

An API Gateway can perform authentication before forwarding requests.

For example:

Client
  ↓
API Gateway
  ↓
Validate Token
  ↓
Authenticated?
  │
 ┌┴─────────┐
 No         Yes
 ↓           ↓
401        Service
Enter fullscreen mode Exit fullscreen mode

This provides a centralized entry point.

However, internal services should still be designed carefully rather than blindly trusting every request from the network.


Distributed Authentication

At large scale, authentication infrastructure itself may be distributed.

A simplified architecture could look like:

                    Users
                      │
                      ▼
                Global Routing
                      │
          ┌───────────┴───────────┐
          ▼                       ▼
     Auth Region A           Auth Region B
          │                       │
          ▼                       ▼
      Auth Servers            Auth Servers
          │                       │
          └───────────┬───────────┘
                      ▼
               User / Identity Data
Enter fullscreen mode Exit fullscreen mode

Now additional challenges appear:

  • Regional availability
  • Data replication
  • Key management
  • Token validation
  • Session consistency
  • Failover
  • Clock synchronization
  • Rate limiting

Authentication becomes part of the overall distributed-system architecture.


What Happens If an Authentication Server Goes Down?

Authentication is often a critical dependency.

If users cannot authenticate, they may not be able to access the application.

Therefore, authentication infrastructure should avoid having a single point of failure.

For example:

                 Load Balancer
                /      |      \
               ▼       ▼       ▼
            Auth 1   Auth 2   Auth 3
               │       │       │
               └───────┼───────┘
                       ▼
                 Shared Data
Enter fullscreen mode Exit fullscreen mode

Multiple authentication servers can provide redundancy.

Health checks and failover mechanisms can route traffic away from unhealthy instances.


Token Validation at Scale

Suppose your application receives millions of API requests.

You don't want every request to perform an expensive remote authentication lookup if it can be avoided.

A common approach is to use signed tokens that services can validate locally.

Request
  ↓
Service
  ↓
Verify Token Signature
  ↓
Check Claims
  ↓
Allow / Reject
Enter fullscreen mode Exit fullscreen mode

This reduces dependency on a centralized authentication lookup for every request.

However, services still need access to trusted signing keys.


Key Management

If JWTs or other signed tokens are used, signing keys become critical infrastructure.

A simplified flow:

Identity Provider
       │
       │ Signs Token
       ▼
    JWT Token
       │
       ▼
   Application
       │
       │ Verify Signature
       ▼
    Valid Token
Enter fullscreen mode Exit fullscreen mode

Keys should be protected carefully.

Large systems may use mechanisms such as:

  • Key rotation
  • Key versioning
  • Secure key storage
  • Public/private key pairs
  • Key distribution endpoints

The goal is to avoid making a single long-lived secret a permanent point of failure.


Logout and Token Revocation

Logging out sounds simple:

User → Logout
Enter fullscreen mode Exit fullscreen mode

But with stateless tokens, there's an important question:

What happens to an access token that has already been issued?

If the token remains valid until expiration, simply deleting it from the client doesn't necessarily invalidate it everywhere.

Possible strategies include:

  • Short-lived access tokens
  • Refresh-token revocation
  • Session tracking
  • Token deny lists
  • Token versioning
  • Centralized authorization checks

The right approach depends on how quickly the system needs to revoke access.


Authentication Rate Limiting

Authentication endpoints are attractive targets for attackers.

For example:

POST /login
POST /signup
POST /forgot-password
POST /refresh-token
Enter fullscreen mode Exit fullscreen mode

These endpoints should typically have appropriate protections such as rate limiting and abuse detection.

A simplified flow:

Login Request
     ↓
Rate Limiter
     ↓
Authentication
     ↓
Success / Failure
Enter fullscreen mode Exit fullscreen mode

This helps prevent excessive login attempts and protects authentication infrastructure from abuse.


A Scalable Authentication Architecture

Putting the concepts together:

                         Users
                           │
                           ▼
                     Load Balancer
                           │
                           ▼
                      API Gateway
                           │
                    Token Validation
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
      User Service     Order Service    Payment Service
          │                │                │
          └────────────────┼────────────────┘
                           │
                      Databases
Enter fullscreen mode Exit fullscreen mode

Alongside the application:

                 Identity Provider
                       │
              ┌────────┴────────┐
              ▼                 ▼
         Access Tokens     Refresh Tokens
Enter fullscreen mode Exit fullscreen mode

This separates identity management from application business logic.


Common Authentication Mistakes

Some common architectural mistakes include:

  • Storing passwords insecurely
  • Making access tokens live too long
  • Putting sensitive information into tokens
  • Sharing authentication secrets carelessly
  • Having a single authentication server
  • Not planning for token revocation
  • Ignoring key rotation
  • Treating OAuth as the same thing as authentication
  • Trusting internal services without proper controls
  • Building authentication independently in every microservice

Authentication is security-critical infrastructure.

It should be designed accordingly.


How Should You Choose?

There isn't one authentication strategy that works for every system.

Small Traditional Web Application

A server-side session can be a simple and effective choice.

Browser
  ↓
Session Cookie
  ↓
Server
  ↓
Session Store
Enter fullscreen mode Exit fullscreen mode

Mobile or API-Heavy Application

Token-based authentication may be more appropriate.

Client
  ↓
Access Token
  ↓
API
Enter fullscreen mode Exit fullscreen mode

Distributed Microservices

A centralized identity provider with signed access tokens can work well.

Identity Provider
       ↓
Access Token
       ↓
API Gateway
       ↓
Microservices
Enter fullscreen mode Exit fullscreen mode

Social Login

OAuth + OpenID Connect is commonly used.

Application
     ↓
Identity Provider
     ↓
User Authentication
     ↓
Application
Enter fullscreen mode Exit fullscreen mode

The Big Picture

Authentication at scale is not just about login forms.

It is about creating a reliable identity system that works across:

  • Multiple servers
  • Multiple services
  • Multiple regions
  • Web applications
  • Mobile applications
  • APIs
  • Third-party identity providers

A simplified evolution might look like:

Simple App
    ↓
Sessions
    ↓
Shared Session Store
    ↓
Token-Based APIs
    ↓
Identity Provider
    ↓
Distributed Authentication
Enter fullscreen mode Exit fullscreen mode

The architecture should evolve as the system's requirements grow.


Key Takeaway

There is no universal winner between sessions, JWTs, and tokens.

Each approach solves a different problem.

Sessions provide centralized server-side control.

JWTs can make token validation easier across distributed services.

Access and refresh tokens provide a flexible pattern for API authentication.

OAuth and OpenID Connect make delegated access and external identity providers possible.

And at large scale, authentication becomes distributed infrastructure that must be designed for security, availability, scalability, and failure.

Authentication isn't just about proving who the user is. At scale, it's about reliably proving identity across an entire distributed system.

Top comments (0)