Concurrent Users Calculator

Concurrent users = arrival rate × average session duration. That is Little's Law, L = λ·W. For example, 20,000 sessions a day lasting 5 minutes on average gives 20,000 ÷ 86,400 s × 300 s ≈ 69 users online at once on average. If 10% of the day's sessions land in the busiest hour, peak concurrency is 2,000 ÷ 3,600 s × 300 s ≈ 167. The calculator below runs this math on your numbers and converts it into requests per second (RPS) for a load test.
The formula behind the calculator
Little's Law says that in any stable system, the average number of items inside it equals the rate at which they arrive multiplied by how long each one stays: L = λ × W. For a website, the "items" are sessions, λ is sessions started per second, and W is the average session duration in seconds. The law holds regardless of the arrival pattern or the duration distribution, as long as you measure λ and W over the same period. The Little's Law guide covers the proof and the other ways it shows up in load testing.
The calculator applies it twice, once for the daily average and once for the busiest hour:
daily_sessions = monthly_sessions / 30 (or the daily value you entered)
λ_avg = daily_sessions / 86,400 s
λ_peak = daily_sessions × peak_hour_share / 3,600 s
W = avg_session_minutes × 60
concurrent_avg = λ_avg × W
concurrent_peak = λ_peak × W
page_views/s = λ × pages_per_session
RPS = page_views/s × requests_per_page_view
peak_factor = λ_peak / λ_avg = peak_hour_share × 24
Note what RPS does not depend on: session duration. Concurrency tells you how many sessions are open at once; request rate is driven only by how often sessions start and how many requests each one makes. Two sites with the same traffic and different session lengths need the same RPS but hold very different numbers of open sessions, which matters for session stores, WebSocket connections and anything that holds per-user memory.
Worked example
An illustrative store with 600,000 sessions per month, the calculator's defaults:
- Daily sessions: 600,000 ÷ 30 = 20,000.
- Average arrival rate: 20,000 ÷ 86,400 = 0.231 sessions/s.
- Average concurrency: 0.231 × 300 s = 69.4 users.
- Peak arrival rate: 10% of 20,000 = 2,000 sessions in the peak hour, ÷ 3,600 = 0.556 sessions/s.
- Peak concurrency: 0.556 × 300 s = 166.7 users.
- Peak RPS: 0.556 sessions/s × 4 pages × 8 requests = 17.8 RPS. The daily average is 7.4 RPS, a 2.4× peak factor.
Those numbers often surprise people: 600,000 visits a month sounds large, yet the origin sees under 20 requests per second at peak. That is normal. Most "how many users can my site handle" questions come down to a few dozen to a few hundred RPS, which is why capacity planning from real traffic beats guessing round numbers like "10,000 users".
Where to get each input
| Input | Source | Watch out for |
|---|---|---|
| Sessions | Analytics sessions/visits, or unique session IDs in access logs | Analytics misses API clients, bots and users who block scripts |
| Session duration | Analytics average engagement or session duration | Time on the last page is usually not counted, so it reads low |
| Peak-hour share | Hourly sessions for your busiest normal day | Use a busy day, not a monthly average; campaigns need their own model |
| Pages per session | Analytics pages/session | SPAs may not record route changes as page views |
| Requests per page view | Browser DevTools Network tab, filtered to your origin domains | Exclude assets served by a CDN cache; include XHR/fetch API calls |
The peak-hour share has a hard floor: a perfectly flat day puts 1/24 (4.17%) of sessions in every hour, so the busiest hour cannot be below that. The calculator flags values under it.
Requests per page view is the input people most often get wrong. A page might trigger 80 requests in the browser, but if 70 of them are images, fonts and scripts served from a CDN edge, your origin sees 10. Load test what your servers actually receive, and test the CDN separately if you need to.
Same concurrency, very different load
Concurrent users alone do not describe load. Here are three illustrative sites, each with 167 peak concurrent users (0.556 sessions/s arriving, 5-minute sessions), but with different behavior per session:
| Site type | Pages/session | Origin requests/page | Peak RPS |
|---|---|---|---|
| Content site behind a CDN | 2 | 2 | 2.2 |
| Store with API-driven pages | 4 | 8 | 17.8 |
| Dashboard SPA with polling | 3 | 40 | 66.7 |
A 30× difference in request rate at identical concurrency. This is the core of the virtual users vs requests per second distinction: concurrency sizes connection pools and session storage, RPS sizes CPU, database throughput and rate limits.
Using the result in a load test
Do not set your load test to "167 virtual users" and press start. A VU in most tools loops through requests as fast as the server answers unless you add think time, so 167 VUs with no think time and a 100 ms response time produce roughly 1,670 RPS, almost 100 times the real peak in the example above.
There are two sound ways to translate the result:
- Target RPS directly (recommended). Use the peak RPS figure, add headroom, and run the test in an arrival-rate mode. The RPS calculator handles peak factors and headroom. In LoadTester this is RPS mode: you set the exact request rate and the platform schedules requests to hold it, independent of response time.
- Model real users with think time. If you want the VU count to match real concurrency, give each VU realistic pauses between steps. The think time and pacing calculator tells you how many VUs a given rate needs once response time and think time are known.
Concurrency is still worth testing on its own when the system holds per-user state: long-polling, WebSockets, server-side sessions. For those, the number of open connections is the load. See concurrent user testing for those cases.
Use concurrent users to size anything that holds a connection or a session. Use RPS to size everything else. Load test with RPS as the controlled variable and check that the resulting concurrency matches the calculator.
Common mistakes
- Spreading monthly traffic evenly. Monthly ÷ 30 ÷ 24 gives the average hour. The peak hour is typically several times higher, and the peak minute higher again.
- Treating the peak hour as flat. Arrivals inside an hour are random and bursty. Little's Law gives the average over the hour; the busiest minute will exceed it. That is one reason to test with 1.5× to 2× headroom.
- Forgetting non-browser traffic. Mobile apps, partner integrations, webhooks and crawlers hit the same backend but do not show up in web analytics. Add them from access logs.
- Mixing time units. Session duration in minutes, arrival rate per second. The calculator converts minutes to seconds; doing it by hand is where most spreadsheet errors creep in.
- Planning for today only. For seasonal peaks such as Black Friday, multiply the peak-hour sessions by your expected uplift before running the numbers.
Checklist before you run the test
- Pull sessions, duration, pages per session and the hourly profile for a busy day.
- Count origin requests per page view in DevTools, excluding CDN-cached assets.
- Compute peak concurrent users and peak RPS above.
- Add headroom (1.5× to 2×) and any campaign uplift to get the test target.
- Run in arrival-rate mode at that RPS, with thresholds on p95 latency and error rate.
- Confirm the concurrency you observe during the test is in line with the calculated number.
FAQ
How do I calculate concurrent users from monthly visitors?
Divide monthly sessions by 30 to get daily sessions, take the share of those that land in your busiest hour, and divide by 3,600 to get sessions per second. Multiply that arrival rate by the average session duration in seconds. That is Little's Law, L = λ·W, and the result is the number of sessions in progress at the same moment.
Is concurrent users the same as virtual users in a load test?
Only if each virtual user behaves like a real visitor, including think time between pages. A VU with zero think time sends requests back to back and generates far more load than a human. Size the test by request rate first, then derive the VU count from response time and think time.
What peak-hour share should I use if I don't have analytics?
A perfectly flat day puts 1/24, about 4.2%, of traffic in each hour, so the peak hour must be at least that. Sites with a regional audience usually have a clear daily peak well above it. Pull the hourly sessions report from your analytics or access logs for a busy day and use the real number; for campaigns or launches, model the expected spike separately.
Why does my analytics session duration look too short?
Most analytics tools measure time between tracked hits, so the time spent on the last page of a session is not counted and single-page sessions often count as zero seconds. That biases average session duration down, which biases concurrency down. Server-side session data or a modest upward adjustment gives a safer number.
Should I load test at exactly the calculated peak?
No. Test at the calculated peak to confirm normal behavior, then add headroom for within-hour bursts and growth, typically 1.5x to 2x, and run a separate step-up or stress test to find the breaking point. The calculated peak is a floor for the test, not a ceiling.