Skip to content
This page View Markdown Open in ChatGPT Open in Claude
WebSocket benchmark · Linode (Akamai Cloud) · Dedicated CPU · 14 October 2026

8 vCPU, 16 GB RAM : 1,732,035 WebSocket clients connected at once.

API Maker 4.0.0 on a Linode Dedicated 16 GB (g6-dedicated-8) : 8 dedicated vCPUs and 16 GB of RAM at $144 a month, its MongoDB and Redis on the same machine. A second server opened WebSocket clients, each with both tokens and a subscription of its own, until the memory of the server was full, while autocannon made the calls which notify them : every run 60 seconds, the memory and CPU of every part sampled each second.

Clients connected 1,732,035 the memory was full : 2,050 MB left
Memory per client 8.8KB API Maker 3.2 · kernel 4.5 · Redis 1.1
New clients / second 10,093 both tokens and a subscription · 19,391 without one
Notification delivered in 0.83ms p50 at 1,000 a second · p99 1.27 ms

The server

Server Linode (Akamai Cloud), Dedicated 16 GB (g6-dedicated-8), dedicated cpu, $144 / month
CPU AMD EPYC 7642 48-Core Processor, 8 dedicated vCPUs (KVM)
KVM guest, 1 thread per core · L1d 512 KiB (8 instances) · L2 4 MiB (8 instances) · L3 128 MiB (8 instances) · BogoMIPS 4600.00
Memory 16 GB (15,991 MB usable), swap 8.5 GB (496 MB of Linode + 8 GB made by the installer)
Disk, region 320 GB SSD, Mumbai, India (ap-west)
System Ubuntu 24.04.4 LTS, Linux 6.8.0-134, Docker 29.9.0
API Maker 4.0.0 : release build of api_maker_be_rust 423a34c with the new WebSocket core of 14 October 2026 (opt-level 3, fat LTO), installed by its installer (https://apimaker.dev/v4/install.sh), no reverse proxy
Settings the defaults of the installer : one worker thread per vCPU, up to 4,093,696 open files for the service (LimitNOFILE), and the sandboxes kept running for the whole run (removeSandboxInactiveSinceMinutes 1440)
Network limits as the installer sets them : 4,093,696 connections tracked by the firewall of Linux (net.netfilter.nf_conntrack_max), 16,384 waiting to be accepted (net.core.somaxconn). The memory of all its TCP connections together : raised by API Maker as the clients came, to 3.9 GB at the most (net.ipv4.tcp_mem, 25 % of the memory ; Linux gives 9 %)
Databases MongoDB 8.0.10 (the MongoDB of API Maker, a replica set of one member, in Docker) · Redis 7.0.5 (the Redis of API Maker, in Docker) : on the same server. No other database runs
Sandboxes TypeScript on Node.js 24.21.0 (an image of 404 MB built by API Maker), 2 sandboxes of the account (sandboxCountForAdmin 2, the default)
Load generator Dedicated 32 GB (g6-dedicated-16) : AMD EPYC 7642 48-Core Processor, 16 dedicated vCPUs, Ubuntu 24.04.4 LTS. The WebSocket clients : am_ws_load, a program in Rust made for these benchmarks, a socket and a task per client, from 101 addresses of the load generator. The HTTP calls : Node.js 24.21.0, autocannon 8.0.0
Network A VLAN of the same data centre, round trip 0.21 ms (ping)
Date 14 October 2026, 03:18 to 04:18 UTC

Only what the run needs was running : API Maker and its two sandboxes, its MongoDB and its Redis. API Maker was restarted and the swap emptied before the run. How every number was taken : How the WebSocket benchmarks are made. Every server side by side : All results. The APIs of this server : 8 vCPU · 16 GB, API benchmark.

The data

  • The clients connect to ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token> : the token of an API user, and the token of a person, a row of the customers table of the benchmark dataset (https://apimaker.dev/json/benchmark_dataset.json) made by a DB token generator. API Maker checks both.
  • A subscription is one REGISTER for the custom WebSocket event order-updates with a condition of its own : { conditionType: 'RESPONSE', criteria: { recipientId: '<the number of the client>' } }. It is the way one notification reaches one person.
  • A notification for one person is 141 bytes ; a row of the dataset told to the clients of a table is 321 bytes.
  • The tables are the ones of the API benchmarks, in MongoDB : ten rows of customers, ten columns each.

Results at a glance

New clients per second
Subscribe : the code reads the databasethe code ran in the sandbox3,919
Subscribe : the code reads the clockthe code ran in the sandbox7,543

100 clients at a time connect, are let in and leave, for 60 seconds.

Notifications per second
A notification for one person21,252 calls / second21,001
A broadcast209 calls / second206,570
Rows inserted in a table1,350 calls / second132,499

As many calls as the server takes : what the clients received each second.

How many clients fit

Clients connect 8,000 a second, level after level, each with both tokens and a subscription of its own ; at each level they wait 30 seconds while the server is sampled (the level the run stops at, 60). The run stopped adding clients at 1,732,035 : the memory of the server was full. 1,964 MB of its 15,992 MB were still counted as available, and Linux had moved 1,187 MB to the swap since the clients began to connect, to make that room : 777 MB were left (the run stops when what is available, less what Linux moved to the swap since the clients began to connect, is under 5 % of the memory of the server).

Clients connected and memory used during the run 00 MB433k3.9 GB866k7.8 GB1.30M11.7 GB1.73M15.6 GB 0 min10 min20 min30 min40 min50 min60 min clients connected memory used, of 15.6 GB
API MakerMongoDB of API MakerRedisSandboxesLinux : its sockets, Docker, the restAvailable
No client
at rest
10,000 clients
connected
100,000 clients
connected
200,000 clients
connected
400,000 clients
connected
600,000 clients
connected
800,000 clients
connected
1,000,000 clients
connected
1,200,000 clients
connected
1,400,000 clients
connected
1,600,000 clients
connected
1,732,035 clients
connected
Clients API Maker Redis Kernel MongoDB Sandboxes Server, used Available Swap CPU busy
None (at rest) 117 1 245 124 55 964 15,028 0 0.5 %
10,000 171 12 375 162 901 1,994 13,998 0 0.6 %
100,000 452 103 699 243 900 2,721 13,271 0 1.0 %
200,000 765 204 1,146 239 900 3,503 12,490 0 2.4 %
400,000 1,413 404 2,039 239 900 5,096 10,895 0 3.7 %
600,000 2,067 625 2,928 239 900 6,720 9,272 0 6.8 %
800,000 2,660 810 3,819 239 900 8,167 7,825 0 9.8 %
1,000,000 3,361 995 4,711 239 900 9,810 6,182 0 12.6 %
1,200,000 3,970 1,249 5,588 239 900 11,403 4,589 0 14.6 %
1,400,000 4,566 1,430 6,429 239 900 12,886 3,106 0 13.7 %
1,600,000 5,143 1,619 7,281 178 625 13,924 2,068 322 16.5 %
1,732,035 5,179 1,736 7,839 52 334 13,942 2,050 1,525 21.8 %

Memory in MB. API Maker is the resident memory of its process ; Redis is the memory of its data (used_memory) ; the kernel of Linux keeps every socket and every tracked connection in its slab ; a container is counted the way docker stats counts it. CPU busy is the whole server while the clients wait : the server pings every client once a minute, and each answers.

Memory when the server is full

With 1,732,035 clients connected and waiting, of the 15,992 MB of the server :

Part At rest, no client 1,732,035 clients More
API Maker (process) 117 MB 5,179 MB + 5,062 MB
Redis (container) 3 MB 1,633 MB + 1,630 MB
Linux kernel : sockets, tracked connections (slab) 245 MB 7,839 MB + 7,594 MB
MongoDB of API Maker (container) 124 MB 52 MB − 71 MB
Sandboxes (2 containers) 55 MB 334 MB + 279 MB
Whole server, used 964 MB 13,942 MB + 12,978 MB
Available 15,028 MB 2,050 MB
Swap used 0 MB 1,525 MB
Open files of API Maker 28 1,732,075
Keys of Redis · channels it listens on 13 · 5 3,464,086 · 1,732,040

MongoDB and the sandboxes grew during the runs before this one (the inserts, the code of the events), not with the clients.

What a client costs

Between 400,000 and 1,400,000 clients (6 levels), each client more cost the server 8.8 KB :

Where Per client What it is
API Maker 3.2 KB The client itself : its socket and the one task which reads it, its tokens and what they said, its subscription and the channel it is told on.
Linux kernel 4.5 KB The TCP socket, and the entry of the connection in the table of the firewall (Docker makes Linux track every connection).
Redis 1.1 KB The subscription : its key, its place in the list of its condition, and the channel API Maker listens on.
In all 8.8 KB 118,886 clients per GB of memory.

Measured over the levels at which nothing was in the swap. The memory the whole server had available went down by 8.0 KB per client : MongoDB, the sandboxes and the cache of files give some back while the clients take theirs.

One more subscription, and a broadcast to everybody

With 200,000 clients connected, every client sent a second REGISTER, for an event without a condition (announcements), 8,000 of them a second : 200,000 were taken in 25.0 s. They waited 30 seconds with two subscriptions each, were told 3 broadcasts, one call of the emit event WS API each, and took the subscription back with UNREGISTER.

One subscription more 1.2KB per client : API Maker 0.5 KB · Redis 0.8 KB
A broadcast to 200k clients 1.79s until the last client read it
Half of them told after 1,230ms the first after 698 ms
Clients told / second 111,544 one call, every client
Broadcast Clients told The call answered after The first client Half of them 99 % of them The last one Clients told a second
1 200,000 of 200,000 1.80 s 698 ms 1,230 ms 1,777 ms 1,793 ms 111,544
2 200,000 of 200,000 1.83 s 667 ms 1,238 ms 1,792 ms 1,828 ms 109,419
3 200,000 of 200,000 1.84 s 698 ms 1,252 ms 1,822 ms 1,837 ms 108,870

One call of the emit event WS API tells every client : API Maker asks Redis for the clients of the event, publishes the notification for each of them, and the server which holds a client sends it. The times are counted from the moment the call is written to the moment a client reads its notification.

Memory, 200,000 clients One subscription each Two subscriptions each A subscription more, per client
API Maker 765 MB 855 MB 0.5 KB
Redis (its data) 204 MB 349 MB 0.8 KB
Keys of Redis · channels 400,016 · 200,005 600,017 · 400,005
Whole server, less available 1.2 KB

New clients per second

How many clients a second the server lets in : 100 clients at a time connect, are let in and leave, one after the other, for 60 seconds (after 5 seconds which are not counted). It is what a server faces when its clients all come back, after a deployment or a network cut. The times are counted from the start of the TCP connection.

Connect : the token of the API user

A client connects with x-am-authorization alone, is told CONNECTED, and leaves. API Maker checks the token of the API user and finds its groups : what every WebSocket client costs before it asks for anything.

Clients / second 21,780 1,308,117 clients in 60 s, 100 at a time
Let in after, p50 2.89ms connected 2.89 ms · TCP 0.25 ms
Let in after, p99 5.26ms max 18.6 ms
Refused or lost 0 not connected, not subscribed, no answer

Server during this run API Maker 7.0 vCPU · MongoDB 0.0 vCPU · whole server busy 92 % · load generator busy 38 %

am_ws_load · Connect : the token of the API user · 60 s
$ am_ws_load churn -c 100 -d 60 "ws://<server>:38246/?x-am-authorization=<token>"
Running 60s test @ ws://<server>:38246
100 clients at a time : connect, CONNECTED, leave

┌─────────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐
│ Stat        │ 2.5%    │ 50%     │ 97.5%   │ 99%     │ Avg     │ Stdev   │ Max      │
├─────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤
│ TCP connect │ 0.18 ms │ 0.25 ms │ 0.47 ms │ 0.61 ms │ 0.28 ms │ 0.22 ms │ 14.88 ms │
├─────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤
│ CONNECTED   │ 1.19 ms │ 2.89 ms │ 4.74 ms │ 5.26 ms │ 2.91 ms │ 0.91 ms │ 18.64 ms │
├─────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤
│ Left        │ 2.62 ms │ 4.49 ms │ 6.92 ms │ 7.52 ms │ 4.56 ms │ 1.14 ms │ 24.67 ms │
└─────────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘
┌─────────────┬────────┬────────┬────────┬────────┬──────────┬────────┬────────┐
│ Stat        │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg      │ Stdev  │ Min    │
├─────────────┼────────┼────────┼────────┼────────┼──────────┼────────┼────────┤
│ Clients/Sec │ 20,954 │ 21,051 │ 21,733 │ 22,688 │ 21,802.0 │ 452.42 │ 20,954 │
└─────────────┴────────┴────────┴────────┴────────┴──────────┴────────┴────────┘

Time from the start of the connection to each step. Clients counted once per second.
# of samples: 60

1.31M clients let in in 60.06s, 0 refused or lost

Connect : both tokens

A client connects with x-am-authorization and x-am-user-authorization, is told CONNECTED, and leaves. Both tokens are checked : the one of the API user, and the one of a person, made by the DB token generator of the account.

Clients / second 19,391 1,164,622 clients in 60 s, 100 at a time
Let in after, p50 3.24ms connected 3.24 ms · TCP 0.26 ms
Let in after, p99 5.98ms max 18.1 ms
Refused or lost 0 not connected, not subscribed, no answer

Server during this run API Maker 7.0 vCPU · MongoDB 0.0 vCPU · whole server busy 92 % · load generator busy 35 %

am_ws_load · Connect : both tokens · 60 s
$ am_ws_load churn -c 100 -d 60 "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
Running 60s test @ ws://<server>:38246
100 clients at a time : connect, CONNECTED, leave

┌─────────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐
│ Stat        │ 2.5%    │ 50%     │ 97.5%   │ 99%     │ Avg     │ Stdev   │ Max      │
├─────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤
│ TCP connect │ 0.18 ms │ 0.26 ms │ 0.49 ms │ 0.69 ms │ 0.28 ms │ 0.21 ms │ 12.37 ms │
├─────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤
│ CONNECTED   │ 1.29 ms │ 3.24 ms │ 5.4 ms  │ 5.98 ms │ 3.26 ms │ 1.03 ms │ 18.11 ms │
├─────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤
│ Left        │ 2.91 ms │ 5.05 ms │ 7.81 ms │ 8.46 ms │ 5.13 ms │ 1.28 ms │ 20.78 ms │
└─────────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘
┌─────────────┬────────┬────────┬────────┬────────┬──────────┬────────┬────────┐
│ Stat        │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg      │ Stdev  │ Min    │
├─────────────┼────────┼────────┼────────┼────────┼──────────┼────────┼────────┤
│ Clients/Sec │ 18,577 │ 18,669 │ 19,382 │ 20,074 │ 19,410.4 │ 399.06 │ 18,577 │
└─────────────┴────────┴────────┴────────┴────────┴──────────┴────────┴────────┘

Time from the start of the connection to each step. Clients counted once per second.
# of samples: 60

1.16M clients let in in 60.06s, 0 refused or lost

Connect with both tokens and subscribe

The whole of what an application does : connect with both tokens, CONNECTED, one REGISTER for a custom WebSocket event with a condition of its own (recipientId : its user id), the answer, then leave. API Maker checks the groups and the auth provider of the event, keeps the subscription in Redis and listens on its channel ; when the client leaves, all of it is taken back.

Clients / second 10,093 606,180 clients in 60 s, 100 at a time
Let in after, p50 8.85ms connected 2.26 ms · TCP 0.24 ms
Let in after, p99 12.8ms max 22.1 ms
Refused or lost 0 not connected, not subscribed, no answer

Server during this run API Maker 5.5 vCPU · Redis 0.5 vCPU · MongoDB 0.0 vCPU · whole server busy 85 % · load generator busy 21 %

am_ws_load · Connect with both tokens and subscribe · 60 s
$ am_ws_load churn -c 100 -d 60 "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>" --register 'order-updates'
Running 60s test @ ws://<server>:38246
100 clients at a time : connect, CONNECTED, REGISTER, leave

┌─────────────┬─────────┬─────────┬──────────┬──────────┬─────────┬─────────┬──────────┐
│ Stat        │ 2.5%    │ 50%     │ 97.5%    │ 99%      │ Avg     │ Stdev   │ Max      │
├─────────────┼─────────┼─────────┼──────────┼──────────┼─────────┼─────────┼──────────┤
│ TCP connect │ 0.18 ms │ 0.24 ms │ 0.43 ms  │ 0.55 ms  │ 0.26 ms │ 0.16 ms │ 11.2 ms  │
├─────────────┼─────────┼─────────┼──────────┼──────────┼─────────┼─────────┼──────────┤
│ CONNECTED   │ 0.72 ms │ 2.26 ms │ 4.52 ms  │ 5.03 ms  │ 2.34 ms │ 1.03 ms │ 15.46 ms │
├─────────────┼─────────┼─────────┼──────────┼──────────┼─────────┼─────────┼──────────┤
│ REGISTER    │ 5.66 ms │ 8.85 ms │ 12.02 ms │ 12.75 ms │ 8.84 ms │ 1.59 ms │ 22.1 ms  │
├─────────────┼─────────┼─────────┼──────────┼──────────┼─────────┼─────────┼──────────┤
│ Left        │ 6.69 ms │ 9.8 ms  │ 13.45 ms │ 14.25 ms │ 9.88 ms │ 1.71 ms │ 22.43 ms │
└─────────────┴─────────┴─────────┴──────────┴──────────┴─────────┴─────────┴──────────┘
┌─────────────┬───────┬───────┬────────┬────────┬──────────┬────────┬───────┐
│ Stat        │ 1%    │ 2.5%  │ 50%    │ 97.5%  │ Avg      │ Stdev  │ Min   │
├─────────────┼───────┼───────┼────────┼────────┼──────────┼────────┼───────┤
│ Clients/Sec │ 9,831 │ 9,845 │ 10,079 │ 10,385 │ 10,103.0 │ 132.36 │ 9,831 │
└─────────────┴───────┴───────┴────────┴────────┴──────────┴────────┴───────┘

Time from the start of the connection to each step. Clients counted once per second.
# of samples: 60

606k clients let in in 60.06s, 0 refused or lost

Subscribe to an event with a can user connect code

The same, on an event whose can user connect code decides who may subscribe : it reads the person of x-am-user-authorization from g.req.auth. The code ran in the server itself (lean code, QuickJS).

Clients / second 8,963 538,318 clients in 60 s, 100 at a time
Let in after, p50 10.0ms connected 2.45 ms · TCP 0.24 ms
Let in after, p99 14.5ms max 29.3 ms
Refused or lost 0 not connected, not subscribed, no answer

Server during this run API Maker 5.8 vCPU · Redis 0.5 vCPU · whole server busy 87 % · load generator busy 17 %

am_ws_load · Subscribe to an event with a can user connect code · 60 s
$ am_ws_load churn -c 100 -d 60 "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>" --register 'checked-token'
Running 60s test @ ws://<server>:38246
100 clients at a time : connect, CONNECTED, REGISTER, leave

┌─────────────┬─────────┬──────────┬──────────┬──────────┬──────────┬─────────┬──────────┐
│ Stat        │ 2.5%    │ 50%      │ 97.5%    │ 99%      │ Avg      │ Stdev   │ Max      │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ TCP connect │ 0.18 ms │ 0.24 ms  │ 0.42 ms  │ 0.52 ms  │ 0.26 ms  │ 0.16 ms │ 12.3 ms  │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ CONNECTED   │ 0.74 ms │ 2.45 ms  │ 4.87 ms  │ 5.39 ms  │ 2.53 ms  │ 1.11 ms │ 15.63 ms │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ REGISTER    │ 6.12 ms │ 10.04 ms │ 13.58 ms │ 14.46 ms │ 9.98 ms  │ 1.84 ms │ 29.31 ms │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ Left        │ 7.32 ms │ 11.09 ms │ 15.12 ms │ 16.06 ms │ 11.13 ms │ 1.95 ms │ 33.44 ms │
└─────────────┴─────────┴──────────┴──────────┴──────────┴──────────┴─────────┴──────────┘
┌─────────────┬───────┬───────┬───────┬───────┬─────────┬────────┬───────┐
│ Stat        │ 1%    │ 2.5%  │ 50%   │ 97.5% │ Avg     │ Stdev  │ Min   │
├─────────────┼───────┼───────┼───────┼───────┼─────────┼────────┼───────┤
│ Clients/Sec │ 8,456 │ 8,762 │ 8,969 │ 9,225 │ 8,972.0 │ 133.80 │ 8,456 │
└─────────────┴───────┴───────┴───────┴───────┴─────────┴────────┴───────┘

Time from the start of the connection to each step. Clients counted once per second.
# of samples: 60

538k clients let in in 60.06s, 0 refused or lost

Subscribe : the code reads the database

The same, with a can user connect code which also reads the person from the database (g.sys.db.getAll with a find) before it answers : one read of MongoDB for every subscription. The code ran in a sandbox of the account.

Clients / second 3,919 235,367 clients in 60 s, 100 at a time
Let in after, p50 23.7ms connected 3.11 ms · TCP 0.22 ms
Let in after, p99 38.4ms max 57.0 ms
Refused or lost 0 not connected, not subscribed, no answer

Server during this run API Maker 2.7 vCPU · Redis 0.3 vCPU · MongoDB 1.2 vCPU · sandboxes 3.0 vCPU · whole server busy 95 % · load generator busy 7 %

am_ws_load · Subscribe : the code reads the database · 60 s
$ am_ws_load churn -c 100 -d 60 "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>" --register 'checked-database'
Running 60s test @ ws://<server>:38246
100 clients at a time : connect, CONNECTED, REGISTER, leave

┌─────────────┬──────────┬──────────┬──────────┬──────────┬──────────┬─────────┬──────────┐
│ Stat        │ 2.5%     │ 50%      │ 97.5%    │ 99%      │ Avg      │ Stdev   │ Max      │
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ TCP connect │ 0.17 ms  │ 0.22 ms  │ 0.43 ms  │ 0.48 ms  │ 0.24 ms  │ 0.15 ms │ 9.89 ms  │
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ CONNECTED   │ 1.05 ms  │ 3.11 ms  │ 7.47 ms  │ 8.56 ms  │ 3.41 ms  │ 1.67 ms │ 17.39 ms │
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ REGISTER    │ 14.49 ms │ 23.74 ms │ 35.65 ms │ 38.4 ms  │ 24.05 ms │ 5.42 ms │ 56.99 ms │
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ Left        │ 15.73 ms │ 25.17 ms │ 37.28 ms │ 39.97 ms │ 25.49 ms │ 5.51 ms │ 57.57 ms │
└─────────────┴──────────┴──────────┴──────────┴──────────┴──────────┴─────────┴──────────┘
┌─────────────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
│ Stat        │ 1%    │ 2.5%  │ 50%   │ 97.5% │ Avg     │ Stdev │ Min   │
├─────────────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤
│ Clients/Sec │ 3,813 │ 3,815 │ 3,909 │ 4,043 │ 3,922.8 │ 67.84 │ 3,813 │
└─────────────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘

Time from the start of the connection to each step. Clients counted once per second.
# of samples: 60

235k clients let in in 60.06s, 0 refused or lost

Subscribe : the code reads the clock

The same, with a can user connect code which reads the time of the machine (Date.now()) : code which is not lean, so API Maker runs it in a sandbox of the account. The code ran in a sandbox of the account.

Clients / second 7,543 453,034 clients in 60 s, 100 at a time
Let in after, p50 12.0ms connected 2.20 ms · TCP 0.22 ms
Let in after, p99 19.4ms max 31.7 ms
Refused or lost 0 not connected, not subscribed, no answer

Server during this run API Maker 4.9 vCPU · Redis 0.4 vCPU · MongoDB 0.0 vCPU · sandboxes 1.4 vCPU · whole server busy 92 % · load generator busy 16 %

am_ws_load · Subscribe : the code reads the clock · 60 s
$ am_ws_load churn -c 100 -d 60 "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>" --register 'checked-sandbox'
Running 60s test @ ws://<server>:38246
100 clients at a time : connect, CONNECTED, REGISTER, leave

┌─────────────┬─────────┬──────────┬──────────┬──────────┬──────────┬─────────┬──────────┐
│ Stat        │ 2.5%    │ 50%      │ 97.5%    │ 99%      │ Avg      │ Stdev   │ Max      │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ TCP connect │ 0.17 ms │ 0.22 ms  │ 0.36 ms  │ 0.42 ms  │ 0.24 ms  │ 0.11 ms │ 9.95 ms  │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ CONNECTED   │ 0.83 ms │ 2.2 ms   │ 4.54 ms  │ 5.1 ms   │ 2.32 ms  │ 0.98 ms │ 14.98 ms │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ REGISTER    │ 7.51 ms │ 11.99 ms │ 17.95 ms │ 19.39 ms │ 12.17 ms │ 2.63 ms │ 31.71 ms │
├─────────────┼─────────┼──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤
│ Left        │ 8.57 ms │ 13.01 ms │ 19.17 ms │ 20.54 ms │ 13.23 ms │ 2.7 ms  │ 32.93 ms │
└─────────────┴─────────┴──────────┴──────────┴──────────┴──────────┴─────────┴──────────┘
┌─────────────┬───────┬───────┬───────┬───────┬─────────┬────────┬───────┐
│ Stat        │ 1%    │ 2.5%  │ 50%   │ 97.5% │ Avg     │ Stdev  │ Min   │
├─────────────┼───────┼───────┼───────┼───────┼─────────┼────────┼───────┤
│ Clients/Sec │ 7,328 │ 7,341 │ 7,556 │ 7,762 │ 7,550.6 │ 107.76 │ 7,328 │
└─────────────┴───────┴───────┴───────┴───────┴─────────┴────────┴───────┘

Time from the start of the connection to each step. Clients counted once per second.
# of samples: 60

453k clients let in in 60.06s, 0 refused or lost

Can user connect code

An event of the WebSocket Events page can carry a can user connect code : API Maker runs it for every subscription to the event, with the tokens of the client in g.req.auth and the subscription in g.req.eventData, and lets the client subscribe when it returns { canConnect: true }. Three codes were measured : one which reads the person of the token, one which also reads the database, one which reads the clock.

Can user connect code of the event checked-token : ran in the server
import * as T from 'types';

async function main(g: T.IAMGlobal) {
    // The person of x-am-user-authorization : only somebody who signed in subscribes, from a country we serve.
    const person = g.req.auth.authAMDB;
    if (!person) return { canConnect: false, errorText: 'Sign in first.' };
    return { canConnect: person.country === 'India', errorText: 'Not available in your country.' };
};
module.exports = main;
Can user connect code of the event checked-database : ran in the sandbox
import * as T from 'types';

async function main(g: T.IAMGlobal) {
    const person = g.req.auth.authAMDB;
    if (!person) return { canConnect: false, errorText: 'Sign in first.' };
    // Still a customer ? One read of the database for every subscription.
    const rows = await g.sys.db.getAll({ instance: 'mongodb', database: 'am_bench', collection: 'customers', queryParams: { find: { customer_id: person.customer_id } } });
    return { canConnect: rows.length === 1 && rows[0].country === 'India', errorText: 'Not a customer any more.' };
};
module.exports = main;
Can user connect code of the event checked-sandbox : ran in the sandbox
import * as T from 'types';

async function main(g: T.IAMGlobal) {
    const person = g.req.auth.authAMDB;
    if (!person) return { canConnect: false, errorText: 'Sign in first.' };
    // The time of the machine : this code runs in the sandbox of the account.
    const hour = new Date(Date.now()).getUTCHours();
    return { canConnect: person.country === 'India' && hour >= 0, errorText: 'Not available in your country.' };
};
module.exports = main;
Can user connect code Runs in Clients / second Subscribed after, p50 p99 Against no code
No code – 10,093 8.85 ms 12.8 ms –
Reads the person of the token the server (QuickJS) 8,963 10.0 ms 14.5 ms 11 % fewer
Reads the person from the database a sandbox of the account 3,919 23.7 ms 38.4 ms 61 % fewer
Reads the clock a sandbox of the account 7,543 12.0 ms 19.4 ms 25 % fewer

Lean code (it only reads what it is handed) runs in the server itself, with QuickJS, on the thread which serves the client. Code which needs more runs in a sandbox of the account : every subscription is then a round trip to the sandbox.

Notifications

With 10,000 clients connected, autocannon makes the HTTP calls which notify them, for 60 seconds, and the clients count what they receive and how late. Each kind of notification is measured twice : at a pace far under what the server takes, which shows how long a notification takes, and with no pace, which shows how many a second the server tells. Delivery is the time from the moment autocannon writes the request to the moment the client reads the notification : the HTTP call, API Maker, Redis, and the WebSocket.

A notification for one person

autocannon calls the emit event WS API with both tokens ; every call names another one of the 10,000 connected clients (recipientId), which is the only one told. The clients measure how long each notification took from the moment its request was written.

Calls / second (paced) 1,000 60,001 calls in 60 s, 10 connections
Notifications / second 983 60,011 received by 10,000 clients
Delivery p50 0.83ms average 0.85 ms
Delivery p99 1.27ms max 4.99 ms
Not delivered 0 0 calls failed

Server during this run API Maker 0.4 vCPU · Redis 0.0 vCPU · whole server busy 6 % · load generator busy 3 %

autocannon · A notification for one person, 1,000 a second

$ autocannon -c 10 -d 60 -R 1000 -l -m POST -b '{"name":"order-updates","eventData":{"recipientId":"<id of a client>","t":<now>,"type":"order-updated","order_no":1001,"status":"SHIPPED"}}' -H "x-am-authorization: <token>" -H "x-am-user-authorization: <token>" -H "content-type: application/json" "http://<server>:38246/api/system-api/bench/emit-event-ws"
Running 60s test @ http://<server>:38246/api/system-api/bench/emit-event-ws
10 connections

┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬──────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%  │ Avg     │ Stdev   │ Max  │
├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼──────┤
│ Latency │ 0 ms │ 0 ms │ 1 ms  │ 1 ms │ 0.42 ms │ 0.51 ms │ 5 ms │
└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴──────┘
┌───────────┬────────┬────────┬────────┬────────┬──────────┬───────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg      │ Stdev │ Min    │
├───────────┼────────┼────────┼────────┼────────┼──────────┼───────┼────────┤
│ Req/Sec   │ 993    │ 994    │ 1,000  │ 1,006  │ 1,000.02 │ 2.34  │ 993    │
├───────────┼────────┼────────┼────────┼────────┼──────────┼───────┼────────┤
│ Bytes/Sec │ 355 kB │ 355 kB │ 357 kB │ 359 kB │ 357 kB   │ 822 B │ 355 kB │
└───────────┴────────┴────────┴────────┴────────┴──────────┴───────┴────────┘

Req/Bytes counts sampled once per second.
# of samples: 60

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 0            │
├────────────┼──────────────┤
│ 0.01       │ 0            │
├────────────┼──────────────┤
│ 0.1        │ 0            │
├────────────┼──────────────┤
│ 1          │ 0            │
├────────────┼──────────────┤
│ 2.5        │ 0            │
├────────────┼──────────────┤
│ 10         │ 0            │
├────────────┼──────────────┤
│ 25         │ 0            │
├────────────┼──────────────┤
│ 50         │ 0            │
├────────────┼──────────────┤
│ 75         │ 1            │
├────────────┼──────────────┤
│ 90         │ 1            │
├────────────┼──────────────┤
│ 97.5       │ 1            │
├────────────┼──────────────┤
│ 99         │ 1            │
├────────────┼──────────────┤
│ 99.9       │ 2            │
├────────────┼──────────────┤
│ 99.99      │ 5            │
├────────────┼──────────────┤
│ 99.999     │ 5            │
└────────────┴──────────────┘

61k requests in 60.03s, 21.4 MB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
10,000 clients subscribed, 64.04s

┌──────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat     │ 2.5%    │ 50%     │ 97.5%   │ 99%     │ Avg     │ Stdev   │ Max     │
├──────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Delivery │ 0.68 ms │ 0.83 ms │ 1.13 ms │ 1.27 ms │ 0.85 ms │ 0.13 ms │ 4.99 ms │
└──────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
┌───────────┬────┬──────┬───────┬───────┬───────┬────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%   │ 97.5% │ Avg   │ Stdev  │ Min │
├───────────┼────┼──────┼───────┼───────┼───────┼────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 1,000 │ 1,000 │ 951.8 │ 213.80 │ 0   │
└───────────┴────┴──────┴───────┴───────┴───────┴────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

60k notifications received in 64.04s (60,011 of 60,001 expected), 10.7 MB read

Calls / second 21,252 1,275,084 calls in 60 s, 100 connections
Notifications / second 21,001 1,275,184 received by 10,000 clients
Delivery p50 4.50ms average 4.53 ms
Delivery p99 6.80ms max 15.5 ms
Not delivered 0 0 calls failed

Server during this run API Maker 6.5 vCPU · Redis 0.3 vCPU · whole server busy 91 % · load generator busy 24 %

autocannon · A notification for one person, as many as the server takes

$ autocannon -c 100 -d 60 -w 10 -l -m POST -b '{"name":"order-updates","eventData":{"recipientId":"<id of a client>","t":<now>,"type":"order-updated","order_no":1001,"status":"SHIPPED"}}' -H "x-am-authorization: <token>" -H "x-am-user-authorization: <token>" -H "content-type: application/json" "http://<server>:38246/api/system-api/bench/emit-event-ws"
Running 60s test @ http://<server>:38246/api/system-api/bench/emit-event-ws
100 connections
10 workers

┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%  │ Avg     │ Stdev   │ Max   │
├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼───────┤
│ Latency │ 3 ms │ 4 ms │ 6 ms  │ 6 ms │ 4.18 ms │ 0.91 ms │ 16 ms │
└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴───────┘
┌───────────┬────────┬─────────┬─────────┬────────┬───────────┬────────┬────────┐
│ Stat      │ 1%     │ 2.5%    │ 50%     │ 97.5%  │ Avg       │ Stdev  │ Min    │
├───────────┼────────┼─────────┼─────────┼────────┼───────────┼────────┼────────┤
│ Req/Sec   │ 19,903 │ 20,511  │ 21,247  │ 21,855 │ 21,252.27 │ 296.68 │ 19,890 │
├───────────┼────────┼─────────┼─────────┼────────┼───────────┼────────┼────────┤
│ Bytes/Sec │ 7.1 MB │ 7.32 MB │ 7.59 MB │ 7.8 MB │ 7.59 MB   │ 106 kB │ 7.1 MB │
└───────────┴────────┴─────────┴─────────┴────────┴───────────┴────────┴────────┘

Req/Bytes counts sampled once per second.
# of samples: 600

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 0            │
├────────────┼──────────────┤
│ 0.01       │ 1            │
├────────────┼──────────────┤
│ 0.1        │ 2            │
├────────────┼──────────────┤
│ 1          │ 2            │
├────────────┼──────────────┤
│ 2.5        │ 3            │
├────────────┼──────────────┤
│ 10         │ 3            │
├────────────┼──────────────┤
│ 25         │ 4            │
├────────────┼──────────────┤
│ 50         │ 4            │
├────────────┼──────────────┤
│ 75         │ 5            │
├────────────┼──────────────┤
│ 90         │ 5            │
├────────────┼──────────────┤
│ 97.5       │ 6            │
├────────────┼──────────────┤
│ 99         │ 6            │
├────────────┼──────────────┤
│ 99.9       │ 8            │
├────────────┼──────────────┤
│ 99.99      │ 10           │
├────────────┼──────────────┤
│ 99.999     │ 13           │
└────────────┴──────────────┘

1275k requests in 60.01s, 455 MB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
10,000 clients subscribed, 63.72s

┌──────────┬─────────┬────────┬─────────┬────────┬─────────┬─────────┬──────────┐
│ Stat     │ 2.5%    │ 50%    │ 97.5%   │ 99%    │ Avg     │ Stdev   │ Max      │
├──────────┼─────────┼────────┼─────────┼────────┼─────────┼─────────┼──────────┤
│ Delivery │ 2.98 ms │ 4.5 ms │ 6.32 ms │ 6.8 ms │ 4.53 ms │ 0.85 ms │ 15.47 ms │
└──────────┴─────────┴────────┴─────────┴────────┴─────────┴─────────┴──────────┘
┌───────────┬────┬──────┬────────┬────────┬──────────┬─────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%    │ 97.5%  │ Avg      │ Stdev   │ Min │
├───────────┼────┼──────┼────────┼────────┼──────────┼─────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 21,244 │ 21,802 │ 20,386.6 │ 3954.42 │ 0   │
└───────────┴────┴──────┴────────┴────────┴──────────┴─────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

1.28M notifications received in 63.72s (1,275,184 of 1,275,084 expected), 228.4 MB read

A broadcast

1,000 more clients subscribe to an event without a condition : every call of the emit event WS API reaches all 1,000 of them.

Calls / second (paced) 5 300 calls in 60 s, 1 connection
Notifications / second 4,931 301,000 received by 1,000 clients
Delivery p50 6.53ms average 7.08 ms
Delivery p99 14.0ms max 29.9 ms
Not delivered 0 0 calls failed

Server during this run API Maker 0.1 vCPU · whole server busy 2 % · load generator busy 3 %

autocannon · A broadcast to 1,000 clients, 5 a second

$ autocannon -c 1 -d 60 -R 5 -l -m POST -b '{"name":"announcements","eventData":{"t":<now>,"type":"announcement","text":"Hello from API Maker"}}' -H "x-am-authorization: <token>" -H "x-am-user-authorization: <token>" -H "content-type: application/json" "http://<server>:38246/api/system-api/bench/emit-event-ws"
Running 60s test @ http://<server>:38246/api/system-api/bench/emit-event-ws
1 connections

┌─────────┬──────┬──────┬───────┬───────┬─────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%   │ Avg     │ Stdev   │ Max   │
├─────────┼──────┼──────┼───────┼───────┼─────────┼─────────┼───────┤
│ Latency │ 1 ms │ 6 ms │ 13 ms │ 14 ms │ 6.58 ms │ 3.64 ms │ 17 ms │
└─────────┴──────┴──────┴───────┴───────┴─────────┴─────────┴───────┘
┌───────────┬────────┬────────┬────────┬────────┬────────┬───────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg    │ Stdev │ Min    │
├───────────┼────────┼────────┼────────┼────────┼────────┼───────┼────────┤
│ Req/Sec   │ 5      │ 5      │ 5      │ 5      │ 5      │ 0     │ 5      │
├───────────┼────────┼────────┼────────┼────────┼────────┼───────┼────────┤
│ Bytes/Sec │ 1.8 kB │ 1.8 kB │ 1.8 kB │ 1.8 kB │ 1.8 kB │ 0 B   │ 1.8 kB │
└───────────┴────────┴────────┴────────┴────────┴────────┴───────┴────────┘

Req/Bytes counts sampled once per second.
# of samples: 60

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 1            │
├────────────┼──────────────┤
│ 0.01       │ 1            │
├────────────┼──────────────┤
│ 0.1        │ 1            │
├────────────┼──────────────┤
│ 1          │ 1            │
├────────────┼──────────────┤
│ 2.5        │ 1            │
├────────────┼──────────────┤
│ 10         │ 2            │
├────────────┼──────────────┤
│ 25         │ 3            │
├────────────┼──────────────┤
│ 50         │ 6            │
├────────────┼──────────────┤
│ 75         │ 9            │
├────────────┼──────────────┤
│ 90         │ 12           │
├────────────┼──────────────┤
│ 97.5       │ 13           │
├────────────┼──────────────┤
│ 99         │ 14           │
├────────────┼──────────────┤
│ 99.9       │ 16           │
├────────────┼──────────────┤
│ 99.99      │ 17           │
├────────────┼──────────────┤
│ 99.999     │ 17           │
└────────────┴──────────────┘

305 requests in 60.04s, 108 kB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
1,000 clients subscribed, 64.05s

┌──────────┬────────┬─────────┬──────────┬──────────┬─────────┬─────────┬──────────┐
│ Stat     │ 2.5%   │ 50%     │ 97.5%    │ 99%      │ Avg     │ Stdev   │ Max      │
├──────────┼────────┼─────────┼──────────┼──────────┼─────────┼─────────┼──────────┤
│ Delivery │ 3.5 ms │ 6.53 ms │ 12.94 ms │ 13.98 ms │ 7.08 ms │ 2.61 ms │ 29.95 ms │
└──────────┴────────┴─────────┴──────────┴──────────┴─────────┴─────────┴──────────┘
┌───────────┬────┬──────┬───────┬───────┬─────────┬─────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%   │ 97.5% │ Avg     │ Stdev   │ Min │
├───────────┼────┼──────┼───────┼───────┼─────────┼─────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 5,000 │ 5,000 │ 4,774.2 │ 1006.74 │ 0   │
└───────────┴────┴──────┴───────┴───────┴─────────┴─────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

301k notifications received in 64.05s (301,000 of 300,000 expected), 46.2 MB read

Calls / second 209 12,537 calls in 60 s, 10 connections
Notifications / second 206,570 12,545,000 received by 1,000 clients
Delivery p50 38.9ms average 39.0 ms
Delivery p99 60.3ms max 92.2 ms
Not delivered 0 0 calls failed

Server during this run API Maker 6.3 vCPU · Redis 0.3 vCPU · whole server busy 87 % · load generator busy 29 %

autocannon · A broadcast to 1,000 clients, as many as the server takes

$ autocannon -c 10 -d 60 -w 10 -l -m POST -b '{"name":"announcements","eventData":{"t":<now>,"type":"announcement","text":"Hello from API Maker"}}' -H "x-am-authorization: <token>" -H "x-am-user-authorization: <token>" -H "content-type: application/json" "http://<server>:38246/api/system-api/bench/emit-event-ws"
Running 60s test @ http://<server>:38246/api/system-api/bench/emit-event-ws
10 connections
10 workers

┌─────────┬───────┬───────┬───────┬───────┬──────────┬─────────┬───────┐
│ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev   │ Max   │
├─────────┼───────┼───────┼───────┼───────┼──────────┼─────────┼───────┤
│ Latency │ 31 ms │ 47 ms │ 63 ms │ 67 ms │ 47.27 ms │ 7.76 ms │ 92 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg     │ Stdev   │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Req/Sec   │ 194     │ 196     │ 207     │ 224     │ 208.95  │ 9.92    │ 194     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Bytes/Sec │ 69.9 kB │ 70.6 kB │ 74.6 kB │ 80.7 kB │ 75.2 kB │ 3.57 kB │ 69.8 kB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘

Req/Bytes counts sampled once per second.
# of samples: 600

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 14           │
├────────────┼──────────────┤
│ 0.01       │ 14           │
├────────────┼──────────────┤
│ 0.1        │ 22           │
├────────────┼──────────────┤
│ 1          │ 28           │
├────────────┼──────────────┤
│ 2.5        │ 31           │
├────────────┼──────────────┤
│ 10         │ 38           │
├────────────┼──────────────┤
│ 25         │ 43           │
├────────────┼──────────────┤
│ 50         │ 47           │
├────────────┼──────────────┤
│ 75         │ 52           │
├────────────┼──────────────┤
│ 90         │ 57           │
├────────────┼──────────────┤
│ 97.5       │ 63           │
├────────────┼──────────────┤
│ 99         │ 67           │
├────────────┼──────────────┤
│ 99.9       │ 75           │
├────────────┼──────────────┤
│ 99.99      │ 85           │
├────────────┼──────────────┤
│ 99.999     │ 92           │
└────────────┴──────────────┘

13k requests in 60.01s, 4.51 MB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
1,000 clients subscribed, 63.73s

┌──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬────────┬──────────┐
│ Stat     │ 2.5%     │ 50%      │ 97.5%    │ 99%      │ Avg      │ Stdev  │ Max      │
├──────────┼──────────┼──────────┼──────────┼──────────┼──────────┼────────┼──────────┤
│ Delivery │ 22.11 ms │ 38.94 ms │ 56.22 ms │ 60.32 ms │ 38.98 ms │ 8.4 ms │ 92.16 ms │
└──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴────────┴──────────┘
┌───────────┬────┬──────┬─────────┬─────────┬───────────┬──────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%     │ 97.5%   │ Avg       │ Stdev    │ Min │
├───────────┼────┼──────┼─────────┼─────────┼───────────┼──────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 206,810 │ 242,904 │ 201,118.4 │ 38561.08 │ 0   │
└───────────┴────┴──────┴─────────┴─────────┴───────────┴──────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

12.54M notifications received in 63.73s (12,545,000 of 12,537,000 expected), 1924.8 MB read

Rows inserted in a table

100 clients subscribe to the insert API of a table (SCHEMA_POST_BULK_INSERT on inserts_public, getEventData: true) ; autocannon inserts rows of the dataset through the insert API, and every row saved is told to each of the 100 clients, with its columns.

Calls / second (paced) 50 3,000 calls in 60 s, 10 connections
Notifications / second 4,931 301,000 received by 100 clients
Delivery p50 12.9ms average 12.8 ms
Delivery p99 19.8ms max 23.6 ms
Not delivered 0 0 calls failed

Server during this run API Maker 0.2 vCPU · Redis 0.0 vCPU · MongoDB 0.1 vCPU · whole server busy 4 % · load generator busy 5 %

autocannon · Inserts told to 100 clients, 50 inserts a second

$ autocannon -c 10 -d 60 -R 50 -l -m POST -b '{"customer_id":1,"first_name":"BENCH","last_name":"INSERT","phone":<now>,"last_update":"2006-02-15T04:34:00.330Z","pincode":111111,"shipping_id":2,"dob":"2022-10-30T03:25:03.000Z","country":"India"}' -H "content-type: application/json" "http://<server>:38246/api/schema/bench/mongodb/am_bench/inserts_public/save-single-or-multiple"
Running 60s test @ http://<server>:38246/api/schema/bench/mongodb/am_bench/inserts_public/save-single-or-multiple
10 connections

┌─────────┬──────┬──────┬───────┬───────┬─────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%   │ Avg     │ Stdev   │ Max   │
├─────────┼──────┼──────┼───────┼───────┼─────────┼─────────┼───────┤
│ Latency │ 1 ms │ 4 ms │ 9 ms  │ 10 ms │ 4.17 ms │ 2.46 ms │ 16 ms │
└─────────┴──────┴──────┴───────┴───────┴─────────┴─────────┴───────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬───────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg     │ Stdev │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼───────┼─────────┤
│ Req/Sec   │ 50      │ 50      │ 50      │ 50      │ 50      │ 0     │ 50      │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼───────┼─────────┤
│ Bytes/Sec │ 30.3 kB │ 30.3 kB │ 30.3 kB │ 30.3 kB │ 30.2 kB │ 0 B   │ 30.2 kB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴───────┴─────────┘

Req/Bytes counts sampled once per second.
# of samples: 60

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 1            │
├────────────┼──────────────┤
│ 0.01       │ 1            │
├────────────┼──────────────┤
│ 0.1        │ 1            │
├────────────┼──────────────┤
│ 1          │ 1            │
├────────────┼──────────────┤
│ 2.5        │ 1            │
├────────────┼──────────────┤
│ 10         │ 1            │
├────────────┼──────────────┤
│ 25         │ 2            │
├────────────┼──────────────┤
│ 50         │ 4            │
├────────────┼──────────────┤
│ 75         │ 6            │
├────────────┼──────────────┤
│ 90         │ 8            │
├────────────┼──────────────┤
│ 97.5       │ 9            │
├────────────┼──────────────┤
│ 99         │ 10           │
├────────────┼──────────────┤
│ 99.9       │ 13           │
├────────────┼──────────────┤
│ 99.99      │ 15           │
├────────────┼──────────────┤
│ 99.999     │ 16           │
└────────────┴──────────────┘

3k requests in 60.04s, 1.81 MB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
100 clients subscribed, 64.05s

┌──────────┬─────────┬──────────┬─────────┬──────────┬──────────┬────────┬──────────┐
│ Stat     │ 2.5%    │ 50%      │ 97.5%   │ 99%      │ Avg      │ Stdev  │ Max      │
├──────────┼─────────┼──────────┼─────────┼──────────┼──────────┼────────┼──────────┤
│ Delivery │ 6.44 ms │ 12.86 ms │ 18.8 ms │ 19.84 ms │ 12.77 ms │ 3.1 ms │ 23.65 ms │
└──────────┴─────────┴──────────┴─────────┴──────────┴──────────┴────────┴──────────┘
┌───────────┬────┬──────┬───────┬───────┬─────────┬─────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%   │ 97.5% │ Avg     │ Stdev   │ Min │
├───────────┼────┼──────┼───────┼───────┼─────────┼─────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 5,000 │ 5,000 │ 4,774.2 │ 1006.74 │ 0   │
└───────────┴────┴──────┴───────┴───────┴─────────┴─────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

301k notifications received in 64.05s (301,000 of 300,000 expected), 94.4 MB read

Calls / second 1,350 81,024 calls in 60 s, 100 connections
Notifications / second 132,499 8,112,100 received by 100 clients
Delivery p50 257ms average 256 ms
Delivery p99 299ms max 339 ms
Not delivered 0 0 calls failed

Server during this run API Maker 5.2 vCPU · Redis 0.2 vCPU · MongoDB 1.1 vCPU · whole server busy 88 % · load generator busy 20 %

autocannon · Inserts told to 100 clients, as many as the server takes

$ autocannon -c 100 -d 60 -w 10 -l -m POST -b '{"customer_id":1,"first_name":"BENCH","last_name":"INSERT","phone":<now>,"last_update":"2006-02-15T04:34:00.330Z","pincode":111111,"shipping_id":2,"dob":"2022-10-30T03:25:03.000Z","country":"India"}' -H "content-type: application/json" "http://<server>:38246/api/schema/bench/mongodb/am_bench/inserts_public/save-single-or-multiple"
Running 60s test @ http://<server>:38246/api/schema/bench/mongodb/am_bench/inserts_public/save-single-or-multiple
100 connections
10 workers

┌─────────┬───────┬───────┬───────┬────────┬──────────┬──────────┬────────┐
│ Stat    │ 2.5%  │ 50%   │ 97.5% │ 99%    │ Avg      │ Stdev    │ Max    │
├─────────┼───────┼───────┼───────┼────────┼──────────┼──────────┼────────┤
│ Latency │ 52 ms │ 73 ms │ 97 ms │ 103 ms │ 73.47 ms │ 11.58 ms │ 148 ms │
└─────────┴───────┴───────┴───────┴────────┴──────────┴──────────┴────────┘
┌───────────┬────────┬────────┬────────┬────────┬─────────┬─────────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg     │ Stdev   │ Min    │
├───────────┼────────┼────────┼────────┼────────┼─────────┼─────────┼────────┤
│ Req/Sec   │ 1,303  │ 1,303  │ 1,344  │ 1,545  │ 1,350.4 │ 42.45   │ 1,303  │
├───────────┼────────┼────────┼────────┼────────┼─────────┼─────────┼────────┤
│ Bytes/Sec │ 788 kB │ 788 kB │ 813 kB │ 935 kB │ 817 kB  │ 25.7 kB │ 788 kB │
└───────────┴────────┴────────┴────────┴────────┴─────────┴─────────┴────────┘

Req/Bytes counts sampled once per second.
# of samples: 600

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 4            │
├────────────┼──────────────┤
│ 0.01       │ 6            │
├────────────┼──────────────┤
│ 0.1        │ 17           │
├────────────┼──────────────┤
│ 1          │ 45           │
├────────────┼──────────────┤
│ 2.5        │ 52           │
├────────────┼──────────────┤
│ 10         │ 60           │
├────────────┼──────────────┤
│ 25         │ 66           │
├────────────┼──────────────┤
│ 50         │ 73           │
├────────────┼──────────────┤
│ 75         │ 80           │
├────────────┼──────────────┤
│ 90         │ 88           │
├────────────┼──────────────┤
│ 97.5       │ 97           │
├────────────┼──────────────┤
│ 99         │ 103          │
├────────────┼──────────────┤
│ 99.9       │ 118          │
├────────────┼──────────────┤
│ 99.99      │ 131          │
├────────────┼──────────────┤
│ 99.999     │ 148          │
└────────────┴──────────────┘

81k requests in 60.02s, 49 MB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
100 clients subscribed, 64.23s

┌──────────┬───────────┬───────────┬───────────┬───────────┬───────────┬──────────┬───────────┐
│ Stat     │ 2.5%      │ 50%       │ 97.5%     │ 99%       │ Avg       │ Stdev    │ Max       │
├──────────┼───────────┼───────────┼───────────┼───────────┼───────────┼──────────┼───────────┤
│ Delivery │ 219.78 ms │ 257.15 ms │ 291.58 ms │ 298.75 ms │ 256.47 ms │ 20.55 ms │ 338.94 ms │
└──────────┴───────────┴───────────┴───────────┴───────────┴───────────┴──────────┴───────────┘
┌───────────┬────┬──────┬─────────┬─────────┬───────────┬──────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%     │ 97.5%   │ Avg       │ Stdev    │ Min │
├───────────┼────┼──────┼─────────┼─────────┼───────────┼──────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 134,114 │ 139,317 │ 129,375.4 │ 25107.08 │ 0   │
└───────────┴────┴──────┴─────────┴─────────┴───────────┴──────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

8.11M notifications received in 64.23s (8,112,100 of 8,102,400 expected), 2544.4 MB read

With every client connected

The same runs once more, with 1,732,035 clients connected and waiting : what a server which is full of WebSocket clients still does.

No client, or 10,000 1,732,035 clients connected
A notification for one person, 1,000 a second : delivery p50 0.83 ms 0.87 ms
… p99 1.27 ms 1.47 ms
A notification for one person, as many as the server takes 21,001 / s 15,938 / s
Get all with both tokens, 100 connections (autocannon) 9,672 req/s 7,305 req/s
… latency p50 / p99 10 ms / 19 ms 10 ms / 92 ms

Calls / second (paced) 1,000 60,000 calls in 60 s, 10 connections
Notifications / second 983 60,010 received by 1,732,035 clients
Delivery p50 0.87ms average 0.90 ms
Delivery p99 1.47ms max 10.7 ms
Not delivered 0 0 calls failed

Server during this run API Maker 1.7 vCPU · Redis 0.0 vCPU · whole server busy 23 % · load generator busy 10 %

autocannon · A notification for one person, 1,000 a second, every client connected

$ autocannon -c 10 -d 60 -R 1000 -l -m POST -b '{"name":"order-updates","eventData":{"recipientId":"<id of a client>","t":<now>,"type":"order-updated","order_no":1001,"status":"SHIPPED"}}' -H "x-am-authorization: <token>" -H "x-am-user-authorization: <token>" -H "content-type: application/json" "http://<server>:38246/api/system-api/bench/emit-event-ws"
Running 60s test @ http://<server>:38246/api/system-api/bench/emit-event-ws
10 connections

┌─────────┬──────┬──────┬───────┬──────┬─────────┬─────────┬───────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%  │ Avg     │ Stdev   │ Max   │
├─────────┼──────┼──────┼───────┼──────┼─────────┼─────────┼───────┤
│ Latency │ 0 ms │ 1 ms │ 1 ms  │ 1 ms │ 0.55 ms │ 0.57 ms │ 10 ms │
└─────────┴──────┴──────┴───────┴──────┴─────────┴─────────┴───────┘
┌───────────┬────────┬────────┬────────┬────────┬────────┬───────┬────────┐
│ Stat      │ 1%     │ 2.5%   │ 50%    │ 97.5%  │ Avg    │ Stdev │ Min    │
├───────────┼────────┼────────┼────────┼────────┼────────┼───────┼────────┤
│ Req/Sec   │ 996    │ 998    │ 1,000  │ 1,003  │ 1,000  │ 0.9   │ 996    │
├───────────┼────────┼────────┼────────┼────────┼────────┼───────┼────────┤
│ Bytes/Sec │ 356 kB │ 356 kB │ 357 kB │ 358 kB │ 357 kB │ 331 B │ 356 kB │
└───────────┴────────┴────────┴────────┴────────┴────────┴───────┴────────┘

Req/Bytes counts sampled once per second.
# of samples: 60

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 0            │
├────────────┼──────────────┤
│ 0.01       │ 0            │
├────────────┼──────────────┤
│ 0.1        │ 0            │
├────────────┼──────────────┤
│ 1          │ 0            │
├────────────┼──────────────┤
│ 2.5        │ 0            │
├────────────┼──────────────┤
│ 10         │ 0            │
├────────────┼──────────────┤
│ 25         │ 0            │
├────────────┼──────────────┤
│ 50         │ 1            │
├────────────┼──────────────┤
│ 75         │ 1            │
├────────────┼──────────────┤
│ 90         │ 1            │
├────────────┼──────────────┤
│ 97.5       │ 1            │
├────────────┼──────────────┤
│ 99         │ 1            │
├────────────┼──────────────┤
│ 99.9       │ 5            │
├────────────┼──────────────┤
│ 99.99      │ 10           │
├────────────┼──────────────┤
│ 99.999     │ 10           │
└────────────┴──────────────┘

61k requests in 60.02s, 21.4 MB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
1,732,035 clients subscribed, 64.03s

┌──────────┬────────┬─────────┬─────────┬─────────┬────────┬─────────┬──────────┐
│ Stat     │ 2.5%   │ 50%     │ 97.5%   │ 99%     │ Avg    │ Stdev   │ Max      │
├──────────┼────────┼─────────┼─────────┼─────────┼────────┼─────────┼──────────┤
│ Delivery │ 0.7 ms │ 0.87 ms │ 1.28 ms │ 1.47 ms │ 0.9 ms │ 0.21 ms │ 10.72 ms │
└──────────┴────────┴─────────┴─────────┴─────────┴────────┴─────────┴──────────┘
┌───────────┬────┬──────┬───────┬───────┬───────┬────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%   │ 97.5% │ Avg   │ Stdev  │ Min │
├───────────┼────┼──────┼───────┼───────┼───────┼────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 1,000 │ 1,000 │ 951.8 │ 213.87 │ 0   │
└───────────┴────┴──────┴───────┴───────┴───────┴────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

60k notifications received in 64.03s (60,010 of 60,000 expected), 10.8 MB read

Calls / second 16,124 967,389 calls in 60 s, 100 connections
Notifications / second 15,938 967,489 received by 1,732,035 clients
Delivery p50 4.78ms average 6.02 ms
Delivery p99 50.5ms max 209 ms
Not delivered 0 0 calls failed

Server during this run API Maker 6.6 vCPU · Redis 0.3 vCPU · MongoDB 0.0 vCPU · whole server busy 92 % · load generator busy 34 %

autocannon · A notification for one person, as many as the server takes, every client connected

$ autocannon -c 100 -d 60 -w 10 -l -m POST -b '{"name":"order-updates","eventData":{"recipientId":"<id of a client>","t":<now>,"type":"order-updated","order_no":1001,"status":"SHIPPED"}}' -H "x-am-authorization: <token>" -H "x-am-user-authorization: <token>" -H "content-type: application/json" "http://<server>:38246/api/system-api/bench/emit-event-ws"
Running 60s test @ http://<server>:38246/api/system-api/bench/emit-event-ws
100 connections
10 workers

┌─────────┬──────┬──────┬───────┬───────┬─────────┬──────────┬────────┐
│ Stat    │ 2.5% │ 50%  │ 97.5% │ 99%   │ Avg     │ Stdev    │ Max    │
├─────────┼──────┼──────┼───────┼───────┼─────────┼──────────┼────────┤
│ Latency │ 3 ms │ 4 ms │ 8 ms  │ 50 ms │ 5.67 ms │ 10.29 ms │ 208 ms │
└─────────┴──────┴──────┴───────┴───────┴─────────┴──────────┴────────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬───────────┬────────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg       │ Stdev  │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼───────────┼────────┼─────────┤
│ Req/Sec   │ 15,231  │ 15,391  │ 16,167  │ 16,703  │ 16,123.74 │ 306.25 │ 15,231  │
├───────────┼─────────┼─────────┼─────────┼─────────┼───────────┼────────┼─────────┤
│ Bytes/Sec │ 5.44 MB │ 5.49 MB │ 5.77 MB │ 5.96 MB │ 5.76 MB   │ 109 kB │ 5.44 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴───────────┴────────┴─────────┘

Req/Bytes counts sampled once per second.
# of samples: 600

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 1            │
├────────────┼──────────────┤
│ 0.01       │ 1            │
├────────────┼──────────────┤
│ 0.1        │ 2            │
├────────────┼──────────────┤
│ 1          │ 2            │
├────────────┼──────────────┤
│ 2.5        │ 3            │
├────────────┼──────────────┤
│ 10         │ 3            │
├────────────┼──────────────┤
│ 25         │ 4            │
├────────────┼──────────────┤
│ 50         │ 4            │
├────────────┼──────────────┤
│ 75         │ 5            │
├────────────┼──────────────┤
│ 90         │ 6            │
├────────────┼──────────────┤
│ 97.5       │ 8            │
├────────────┼──────────────┤
│ 99         │ 50           │
├────────────┼──────────────┤
│ 99.9       │ 150          │
├────────────┼──────────────┤
│ 99.99      │ 189          │
├────────────┼──────────────┤
│ 99.999     │ 207          │
└────────────┴──────────────┘

967k requests in 60.01s, 345 MB read

am_ws_load · what the clients received

$ am_ws_load listen "ws://<server>:38246/?x-am-authorization=<token>&x-am-user-authorization=<token>"
1,732,035 clients subscribed, 63.71s

┌──────────┬─────────┬─────────┬─────────┬──────────┬─────────┬──────────┬───────────┐
│ Stat     │ 2.5%    │ 50%     │ 97.5%   │ 99%      │ Avg     │ Stdev    │ Max       │
├──────────┼─────────┼─────────┼─────────┼──────────┼─────────┼──────────┼───────────┤
│ Delivery │ 3.14 ms │ 4.78 ms │ 7.91 ms │ 50.53 ms │ 6.02 ms │ 10.27 ms │ 208.64 ms │
└──────────┴─────────┴─────────┴─────────┴──────────┴─────────┴──────────┴───────────┘
┌───────────┬────┬──────┬────────┬────────┬──────────┬─────────┬─────┐
│ Stat      │ 1% │ 2.5% │ 50%    │ 97.5%  │ Avg      │ Stdev   │ Min │
├───────────┼────┼──────┼────────┼────────┼──────────┼─────────┼─────┤
│ Notif/Sec │ 0  │ 0    │ 16,180 │ 16,626 │ 15,520.3 │ 2928.12 │ 0   │
└───────────┴────┴──────┴────────┴────────┴──────────┴─────────┴─────┘

Delivery : from the moment the request is written to the moment the client reads the notification.
# of samples: 64

967k notifications received in 63.71s (967,489 of 967,389 expected), 175.4 MB read

Requests / second 7,305 438,273 requests in 60 s
Latency p50 10ms average 13.19 ms
Latency p99 92ms max 289 ms
Errors 0 non-2xx, errors, timeouts

Server during this run API Maker 4.9 vCPU · Redis 0.1 vCPU · MongoDB 1.9 vCPU · whole server busy 96 % · load generator busy 23 %

autocannon · get all with both tokens · 1,732,035 WebSocket clients connected

$ autocannon -c 100 -d 60 -w 10 -l -H "x-am-authorization: <token>" -H "x-am-user-authorization: <token>" "http://<server>:38246/api/schema/bench/mongodb/am_bench/customers"
Running 60s test @ http://<server>:38246/api/schema/bench/mongodb/am_bench/customers
100 connections
10 workers

┌─────────┬──────┬───────┬───────┬───────┬──────────┬──────────┬────────┐
│ Stat    │ 2.5% │ 50%   │ 97.5% │ 99%   │ Avg      │ Stdev    │ Max    │
├─────────┼──────┼───────┼───────┼───────┼──────────┼──────────┼────────┤
│ Latency │ 5 ms │ 10 ms │ 43 ms │ 92 ms │ 13.19 ms │ 15.85 ms │ 289 ms │
└─────────┴──────┴───────┴───────┴───────┴──────────┴──────────┴────────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬────────┬─────────┐
│ Stat      │ 1%      │ 2.5%    │ 50%     │ 97.5%   │ Avg      │ Stdev  │ Min     │
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼────────┼─────────┤
│ Req/Sec   │ 6,475   │ 6,631   │ 7,351   │ 7,555   │ 7,305.07 │ 218.23 │ 6,473   │
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼────────┼─────────┤
│ Bytes/Sec │ 17.7 MB │ 18.1 MB │ 20.1 MB │ 20.7 MB │ 20 MB    │ 596 kB │ 17.7 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴────────┴─────────┘

Req/Bytes counts sampled once per second.
# of samples: 600

┌────────────┬──────────────┐
│ Percentile │ Latency (ms) │
├────────────┼──────────────┤
│ 0.001      │ 0            │
├────────────┼──────────────┤
│ 0.01       │ 1            │
├────────────┼──────────────┤
│ 0.1        │ 2            │
├────────────┼──────────────┤
│ 1          │ 4            │
├────────────┼──────────────┤
│ 2.5        │ 5            │
├────────────┼──────────────┤
│ 10         │ 6            │
├────────────┼──────────────┤
│ 25         │ 8            │
├────────────┼──────────────┤
│ 50         │ 10           │
├────────────┼──────────────┤
│ 75         │ 13           │
├────────────┼──────────────┤
│ 90         │ 17           │
├────────────┼──────────────┤
│ 97.5       │ 43           │
├────────────┼──────────────┤
│ 99         │ 92           │
├────────────┼──────────────┤
│ 99.9       │ 198          │
├────────────┼──────────────┤
│ 99.99      │ 236          │
├────────────┼──────────────┤
│ 99.999     │ 273          │
└────────────┴──────────────┘

438k requests in 60.02s, 1.2 GB read

Questions

How many WebSocket connections can API Maker hold on 8 dedicated vCPUs and 16 GB ?

1,732,035 clients were connected at the same time on this server, each with both tokens and a subscription of its own, with MongoDB, Redis and two sandboxes on the same machine. Memory is what ends first : a client costs about 8.8 KB of the server in all.

How much memory does a WebSocket client cost ?

About 8.8 KB : 3.2 KB in the API Maker process, 4.5 KB in the Linux kernel (its socket) and 1.1 KB in Redis (its subscription). Measured between 400,000 and 1,400,000 clients which wait, each connected with both tokens and one subscription.

How many clients can connect each second ?

10,093 clients a second connected with both tokens, subscribed and left, 100 at a time ; 19,391 a second without a subscription. With a can user connect code on the event : 8,963 a second.

How fast does a notification reach a client ?

At 1,000 notifications a second, each for one person among 10,000 : 0.83 ms from the HTTP call to the client (p50), 1.27 ms for 99 % of them. With as many calls as the server takes : 21,001 notifications a second.

Do connected WebSocket clients slow the APIs down ?

Get all with both tokens answered 9,672 requests a second with no WebSocket client, and 7,305 with 1,732,035 clients connected and waiting. A client which waits costs memory ; its CPU is a ping a minute.