Methodology8 min

Translating Users to Load: the math behind tests

How many requests per second represent 1000 users? Learn to translate business metrics into realistic technical load.

"We need to handle 100,000 simultaneous users." Seems clear, but what does that mean technically? How many requests per second? How many connections? How much CPU? Translating business metrics to technical load is one of the most important — and most poorly executed — skills in performance engineering.

Simultaneous users is a business metric. Requests per second is a technical metric. Knowing how to translate between them is essential.

The Translation Problem

Ambiguity of "users"

What "100K users" can mean:

1. Registered users: 100K accounts
   → Relevance for load: zero

2. Monthly active users (MAU): 100K
   → Maybe 10% online at peak

3. Daily active users (DAU): 100K
   → Maybe 20% online at peak

4. Simultaneous users: 100K
   → Connected at the same time

5. Users taking actions: 100K
   → Generating requests now

The practical difference

Scenario: "100K active users"

Wrong interpretation:
  100K users × 1 req/s = 100K req/s
  (users don't make 1 request per second)

Correct interpretation:
  100K users online
  ÷ 30s between actions (think time)
  = 3,333 req/s

Difference: 30x

Load Model: Little's Law

The fundamental formula

L = λ × W

Where:
L = Number of concurrent requests (in processing)
λ = Arrival rate (requests/second)
W = Average processing time (seconds)

Example:
λ = 100 req/s
W = 0.2s (200ms)
L = 100 × 0.2 = 20 simultaneous requests

Inverse application

If you know:
- How many users online: U
- Average think time: T (seconds between actions)
- Actions per session: A

Request rate = U × A / T

Example:
U = 10,000 users online
T = 30s think time
A = 1 (one action)

Rate = 10,000 × 1 / 30 = 333 req/s

Modeling Real Behavior

Conversion funnel

Input: 100K visitors/hour

Funnel:
  Home page: 100K (100%)
  Listing: 70K (70%)
  Product: 50K (50%)
  Add cart: 10K (10%)
  Checkout: 5K (5%)
  Payment: 4K (4%)

Requests per endpoint:
  GET /           : 100K/h = 28 req/s
  GET /products   : 70K/h = 19 req/s
  GET /product/:id: 50K/h = 14 req/s
  POST /cart      : 10K/h = 3 req/s
  GET /checkout   : 5K/h = 1.4 req/s
  POST /payment   : 4K/h = 1.1 req/s

Total: ~66 req/s

Multiple requests per page

Product page loads:
  - HTML: 1 request
  - Product API: 1 request
  - Related API: 1 request
  - Reviews API: 1 request
  - Images: 5 requests
  - JS/CSS: 3 requests

Total: 12 requests per page view

If 50K page views/hour:
  50K × 12 = 600K requests/hour
  = 167 req/s (not 14 req/s!)

Realistic think time

Think time distribution (seconds):

Action            | Mean | p50 | p95
------------------|------|-----|-----
Read home page    | 15   | 10  | 60
Browse listing    | 20   | 15  | 90
Analyze product   | 45   | 30  | 180
Decide to buy     | 60   | 45  | 300
Fill checkout     | 120  | 90  | 400

Don't use fixed values!
Use distribution (log-normal works well)

Load Calculator

Calculation template

## Load Calculation - [System]

### Business Assumptions
- Active users at peak: 50,000
- Average session: 10 minutes
- Average think time: 30 seconds
- Actions per session: 20

### Base Calculation
Action rate = 50,000 / 30 = 1,667 actions/s

### By Endpoint (based on analytics)
| Endpoint | % traffic | req/s |
|----------|-----------|-------|
| GET /api/products | 40% | 667 |
| GET /api/product/:id | 30% | 500 |
| POST /api/cart | 15% | 250 |
| GET /api/checkout | 10% | 167 |
| POST /api/payment | 5% | 83 |

### Multipliers
- Cache misses (30%): +500 req/s to DB
- Retries (5%): +83 req/s total
- Healthchecks: +10 req/s

### Total Estimated Load
- API: 1,667 req/s
- DB queries: 2,500 req/s
- Cache ops: 4,000 req/s

### Safety Margin (2x)
- Target: 3,334 req/s sustained
- Peak: 5,000 req/s for 5 minutes

Calculation script

def calculate_load(
    active_users: int,
    think_time_seconds: float,
    session_duration_minutes: float,
    pages_per_session: float,
    requests_per_page: float,
    safety_margin: float = 2.0
) -> dict:
    """
    Calculate technical load from business metrics
    """
    # Base page view rate
    page_views_per_second = active_users / think_time_seconds

    # Request rate (including assets, APIs, etc)
    requests_per_second = page_views_per_second * requests_per_page

    # Concurrent requests (Little's Law)
    avg_response_time = 0.2  # assuming 200ms
    concurrent_requests = requests_per_second * avg_response_time

    return {
        "page_views_per_second": round(page_views_per_second, 1),
        "requests_per_second": round(requests_per_second, 1),
        "concurrent_requests": round(concurrent_requests, 1),
        "target_with_margin": round(requests_per_second * safety_margin, 1),
        "peak_capacity": round(requests_per_second * safety_margin * 1.5, 1)
    }

# Example
result = calculate_load(
    active_users=50000,
    think_time_seconds=30,
    session_duration_minutes=10,
    pages_per_session=20,
    requests_per_page=8
)

print(result)
# {
#   'page_views_per_second': 1666.7,
#   'requests_per_second': 13333.3,
#   'concurrent_requests': 2666.7,
#   'target_with_margin': 26666.7,
#   'peak_capacity': 40000.0
# }

Validating the Model

Compare with production

-- Peak requests per second
SELECT
  date_trunc('minute', timestamp) as minute,
  count(*) / 60.0 as rps
FROM access_logs
WHERE timestamp > now() - interval '7 days'
GROUP BY 1
ORDER BY rps DESC
LIMIT 10;

-- Peak unique users per minute
SELECT
  date_trunc('minute', timestamp) as minute,
  count(distinct user_id) as unique_users
FROM access_logs
WHERE timestamp > now() - interval '7 days'
GROUP BY 1
ORDER BY unique_users DESC
LIMIT 10;

Calculate real ratio

-- Requests per active user
WITH hourly AS (
  SELECT
    date_trunc('hour', timestamp) as hour,
    count(*) as requests,
    count(distinct user_id) as users
  FROM access_logs
  WHERE timestamp > now() - interval '7 days'
  GROUP BY 1
)
SELECT
  avg(requests::float / nullif(users, 0)) as req_per_user_hour,
  avg(requests::float / nullif(users, 0) / 3600) as req_per_user_second
FROM hourly;

Common Pitfalls

1. Ignoring the funnel

❌ "100K users × 10 req/s = 1M req/s"

✅ Model the funnel:
   100K view home
   30K see product
   3K checkout
   → Requests vary by stage

2. Robot think time

❌ "Virtual user makes request, waits 1s, makes request"

✅ Realistic think time:
   Average 30s, log-normal distribution
   Varies by page type

3. Forgetting internal requests

❌ "I only calculated API requests"

✅ Include:
   - Service-to-service calls
   - DB queries per request
   - Cache operations
   - Background jobs triggered

4. Peak = Average

❌ "Average of 1000 req/s, I'll test 1000"

✅ Model peaks:
   Peak can be 3-5x the average
   Test for peak, not average

Complete Example

Scenario: Black Friday

## Capacity Planning - Black Friday

### History
- Black Friday 2023: 80K users peak
- Projected growth: 50%
- Target 2024: 120K users peak

### Load Model

**Active users at peak**: 120,000

**Distribution by journey**:
| Journey | % | Users | Think time | Req/s |
|---------|---|-------|------------|-------|
| Browse | 60% | 72K | 20s | 3,600 |
| Search | 25% | 30K | 15s | 2,000 |
| Checkout | 15% | 18K | 45s | 400 |

**Base total**: 6,000 req/s

**Multipliers**:
- Requests per page: ×8 = 48,000 req/s
- Cache miss (40%): +19,200 DB queries/s
- Margin (2x): 96,000 req/s

### Infrastructure Requirements
- API servers: 96K / 2K per instance = 48 instances
- DB connections: 19.2K × 0.1s = 1,920 concurrent
- Cache: 48K × 0.01s = 480 concurrent ops

### Validation Test
- Sustained load: 50K req/s for 2h
- Peak: 100K req/s for 15min
- Spike: 150K req/s for 1min

Conclusion

Translating users to load requires:

  1. Understand what "users" means in context
  2. Model the behavior funnel
  3. Calculate realistic think time
  4. Include all requests (not just main API)
  5. Validate against real production data
  6. Apply safety margin for peaks

The number of users is the input. The number of requests is the output. The math in between is what separates success from failure.


This article is part of the series on the OCTOPUS Performance Engineering methodology.

OCTOPUSload testingcapacitycalculation

Want to understand your platform's limits?

Contact us for a performance assessment.

Contact Us