·
How much load Versola carries per node, and what it costs
Measured on Yandex Cloud Kazakhstan: one 8-vCPU node with one auth and one edge pod sustains about 2,350 steps per second, three nodes about 4,680. Throughput, latency, edge overhead, CPU, database load and monthly cost in dollars.
We wanted one number we could put in front of a CTO: how many nodes does a given load need, and what does that cost per month. This post gives the number and the method behind it.
The short version: on the 0.7 build, one 8-vCPU node running one auth pod and one edge pod handles about 2,350 steps per second inside the latency limits. Three such nodes handle about 4,680. The price of that capacity on Yandex Cloud Kazakhstan, converted to dollars, is shown below. A “step” is one request of a user scenario: a business call through the edge, a token refresh, a code exchange, a login step or a logout.
* Yandex Cloud Kazakhstan list prices, VAT included, converted at 1 $ = 450 ₸. The prices are approximate and may change.
What we measured
The stand is a Kubernetes cluster in the kz1-a zone. The nodes are 8 vCPU, 16 GB RAM, Intel Ice Lake. The databases are managed PostgreSQL: one for auth and central, one for edge. A load generator running on separate nodes drives a population of one million registered users through the full scenario mix: login with OTP, password or passkey, token refresh, code exchange, step-up, business calls through the edge to an upstream API, and logout.
Two details matter for reading the results.
- The upstream API is a mock, and OTP codes are fake, so the numbers cover Versola’s own work, not an SMS gateway or a real business service. The password check is real Argon2.
- Pods are sized the same on every node: each
authandedgepod requests 2 CPU, has no CPU limit and a 1 GiB memory limit (JVM heap 512 MiB). Each node runs exactly oneauthand oneedgepod, so adding a node adds a whole pair.
Load grows in steps. Each step has a 1-minute warm-up, a 4-minute ramp and a 6-minute plateau, and the figures here come from the plateau. A step passes when the failure rate is below 2% and the latency stays inside the limits (p99 of a token refresh under 250 ms, p99 of a business call under 300 ms). A step that fails is repeated once. “Clean” means the last step that passed.
Capacity by number of nodes
| Nodes | Clean, steps/s | Per node | Share of linear | Token refresh p99 | Code exchange p99 |
|---|---|---|---|---|---|
| 1 | 2,352 | 2,352 | 100% | 44 ms | 54 ms |
| 2 | 3,639 | 1,819 | 77% | 27 ms | 32 ms |
| 3 | 4,679 | 1,560 | 66% | 26 ms | 29 ms |
Capacity does not grow in a straight line. Read the share-of-linear column with the ladder in mind: load rose in coarse steps, so the last clean step is a lower bound. One step above it, the two- and three-node setups did not collapse. They kept serving 4,260 steps/s (two nodes, 90% of linear) and 5,630 steps/s (three nodes, 80%) with fewer than 0.1% failed requests, but with a p99 of 2.7 to 3.4 seconds, which is outside the limit.
What the load consisted of
Per second at one node, at the clean step:
| Step type | Per second | Share |
|---|---|---|
| Business calls through the edge | 1,052 | 55% |
| Token refreshes | 454 | 24% |
| Login: authorize, phone, challenge, PAR | 243 | 13% |
| Authorization-code exchanges | 46 | 2% |
| OTP submissions | 40 | 2% |
| Logouts | 33 | 2% |
| Passkey assertions | 24 | 1% |
| Password checks (Argon2) | 12 | 1% |
The mix keeps these shares at two and three nodes. The ratio of token refreshes to code exchanges is 10, the upper end of the profile we target (5 to 10 refreshes per code exchange).
Between the two services the work splits like this, at one node:
| Service | Requests per second | What it handles |
|---|---|---|
edge | 1,554 | proxied resource calls 989, native-app endpoints 508, sessions and logout 18, other 38 |
auth | 980 | token refresh 421, login flow (authorize, PAR, challenge) 322, userinfo 157, code exchange 62, other 19 |
One business call is one request to the edge and, on some calls, an extra userinfo or refresh request to auth, so the two services see different request counts for the same steps. At three nodes the figures are 3,133 requests per second on the edge and 1,967 on auth.
Latency and edge overhead
Edge overhead is what the edge adds to a proxied call itself, leaving out the time spent waiting for the upstream. It is measured by the proxy-overhead histogram of the edge.
| 1 node | 2 nodes | 3 nodes | |
|---|---|---|---|
| Edge overhead p50 | 2.0 ms | 1.8 ms | 1.7 ms |
| Edge overhead p99 | 23.5 ms | 18.2 ms | 11.0 ms |
| Token refresh p99 | 44 ms | 27 ms | 26 ms |
| Code exchange p99 | 54 ms | 32 ms | 29 ms |
| Password check p99 (Argon2) | 155 ms | 111 ms | 108 ms |
| Passkey assertion p99 | 61 ms | 47 ms | 44 ms |
The p99 figures at one node are higher because that run sat closest to its limit.
Resources
At three nodes, on the clean step:
- CPU: 2.1 cores per 1,000 steps/s in total,
auth1.01 andedge1.14. The pods peak at 5.3 and 5.9 cores out of 24 allocatable, so 53% of the cluster is unused at that load. - Memory: peak 870 MiB per
authpod and 775 MiB peredgepod against a 1 GiB limit. Garbage collection takes 1.5% to 1.6% of the time. - Database: the
authdatabase takes 7,347 transactions per second and writes 648 KiB/s of WAL. The application holds 7 database connections in use on average and 15 at peak.
Why we count in nodes, not pods
The auth and edge pods have a CPU request but no CPU limit, so under load a pod takes as many cores as the node has free. In earlier runs one auth pod alone reached 7.4 of 7.9 allocatable cores. The ceiling is therefore the CPU of the node, shared by its auth, edge and system pods. Adding pods to a node that is already busy adds nothing; adding a node adds a whole pair.
What it costs
Prices are Yandex Cloud Kazakhstan list prices, VAT included, per month, converted at 1 $ = 450 ₸. They are approximate and may change.
| Item | $ per month* |
|---|---|
| Kubernetes master (zonal, 2 vCPU / 8 GB) and its public IP | $100 |
PostgreSQL for auth and central (c3-c8-m16, 150 GB SSD) | $306 |
PostgreSQL for edge (c3-c4-m8, 50 GB SSD) | $147 |
| Fixed part | $553 |
| One worker node (8 vCPU, 16 GB RAM, 64 GB SSD) | $188 |
| Nodes | Planned load, steps/s | $ per month* | $ per 1,000 planned steps/s* |
|---|---|---|---|
| 1 | 1,647 | $741 | $450 |
| 2 | 2,547 | $928 | $364 |
| 3 | 3,275 | $1,116 | $341 |
The cost per 1,000 steps/s is the monthly total divided by the planned load, where the planned load is 70% of the clean figure. It falls as more nodes share the fixed part. Growth costs $114* per month for every further 1,000 planned steps/s: that is one more node, $188*, divided by the planned load of one node. It counts nodes only. The databases did not grow in this test and were not pushed past about 4,000 steps per second.
The prices come from the public Yandex Cloud Kazakhstan price catalog (the billing SKU list, fetched on 2026-10-16), applied to the real configuration of the stand: vCPU, RAM and disk of each node and database host, 730 hours a month. Not counted: the network load balancer in front of the ingress (about $11* a month), outgoing traffic, extra backup storage and support.