Run a community Looking after the server

How big a server

Short answer: a lot more than a small group needs. On a server with half a CPU and 512 MB of memory, Sideporch kept messages arriving within a fraction of a second for 4,800 people online at once, each of them posting every two minutes. Most teams are nowhere near that.

ServerPeople online at once, still fastMemory used then
½ CPU, 512 MB4,80094 MB
1 CPU, 1 GB9,600193 MB
2 CPUs, 2 GB12,800 or more (the most tested)255 MB

“Fast” means 95% of messages are posted, and reach everyone looking at the channel, within one second. Nothing may fail, and nobody may fall behind.

What to run

These numbers came from a fast machine, and real servers’ CPUs are often slower. To leave room, plan with a quarter of them:

  • Up to 1,000 people online at once: the smallest VPS you can find, a Raspberry Pi 4, or any home server. Half a CPU and 512 MB are plenty.
  • Up to 2,500: 1 CPU and 1 GB.
  • Up to 5,000: 2 CPUs and 2 GB.
  • More than that: it will likely work on bigger machines, but it wasn’t tested. Sideporch runs on one server with SQLite, which is not built for organisations of tens of thousands.

People online at once are usually a fraction of everyone with an account. Accounts themselves cost almost nothing: the tests had 12,800.

Reading aloud and dictation are the exception: while in use, their models take 0.6 to 3.5 GB of memory, and they run one at a time. Small servers are better off with Whisper tiny, or no speech models.

Signing in is deliberately slow work. Passwords are checked with Argon2, about 6 sign-ins a second on half a CPU. Sessions last 30 days, so this only matters if hundreds of people sign in at the same moment.

Disk grows with what people post and upload; text is small, and files take their own size.

How it was measured

The load generator in tools/loadtest/ simulates people the way browsers use Sideporch:

  • Each person keeps a live connection open.
  • Each person looks at one of 10 channels, spread evenly.
  • Each person posts a message there every two minutes on average (random intervals), and reloads the channel page every five minutes.
  • It measures how long each post takes, how long until everyone else looking at that channel has the message, and how long pages take.

Posting every two minutes is far busier than most teams: 30 messages an hour, per person. With 10 channels, every channel has hundreds or thousands of people looking at it. Both make the test harsher than real use.

Each server size is a container with those CPU and memory limits, running the same image people install. It ran in Colima on an Apple silicon Mac, next to the load generator, and started from a database with 12,800 accounts. Each step ran for a minute after everyone had connected; server CPU and memory were sampled every two seconds.

To run it yourself:

# Build the load generator for Linux, once:
docker run --rm -v "$PWD/tools/loadtest":/src -w /src rust:1-slim-bookworm \
  cargo build --release --target-dir /src/target-linux
# Then pick sizes (CPUs:memory) and numbers of people:
tools/loadtest/run.sh "0.5:512m 1:1g" "100 400 1600 3200"
tools/loadtest/report.sh

What limits it

For most of the range, the limit is CPU: fanning messages out to everyone who sees them. Memory stays small, at about 20 KB per connected person plus a few megabytes.

Version 0.3.0 did much worse:

Server0.3.0Now
½ CPU, 512 MB1,2004,800
1 CPU, 1 GB1,6009,600
2 CPUs, 2 GB2,40012,800+

These load tests found four problems, all fixed now:

  • Every browser got every message in full. Sideporch 0.3.0 sent every new message, fully rendered, to every connected browser, whether or not it showed that channel. The work grew with the square of the people online. Browsers now say which channel they show; everyone else gets a short “something new” notice, once until they read it.
  • Rendering rebuilt everyone’s usernames. Every message and page rebuilt a list of all usernames and custom emoji. It is now kept until accounts or emoji change.
  • Mentions checked every account. Finding who a message mentions scanned every account; it now looks up only the names in the message.
  • WebSocket buffers took most of the memory. Each connection reserved 128 KB buffers, about 145 KB per person online. That filled half a gigabyte at 4,800 people. They are now sized for the small messages Sideporch sends.

All results

Latencies are the 95th and 99th percentiles over the minute. “Seen” is from posting until the message reached everyone else looking at the channel. Server CPU is the average share of one core. The 0.3.0 runs started from 3,200 accounts, the others from 12,800.

0.3.0: ½ CPU, 512 MB

People onlineMessages/sPost p95Seen p95Seen p99Page p95Server CPU (avg)Memory (max)Result
500.410 ms16 ms19 ms10 ms1 %13 MiBok
1000.710 ms23 ms25 ms9 ms2 %23 MiBok
2001.916 ms35 ms70 ms9 ms6 %40 MiBok
4003.487 ms113 ms184 ms72 ms15 %74 MiBok
8006.9203 ms280 ms337 ms213 ms33 %137 MiBok
12009.9542 ms762 ms906 ms524 ms44 %213 MiBok
160013.42.2 s2.9 s3.3 s2.3 s46 %289 MiBtoo slow

0.3.0: 1 CPU, 1 GB

People onlineMessages/sPost p95Seen p95Seen p99Page p95Server CPU (avg)Memory (max)Result
500.411 ms18 ms21 ms9 ms1 %13 MiBok
1000.813 ms25 ms30 ms12 ms2 %21 MiBok
2001.711 ms36 ms40 ms8 ms6 %42 MiBok
4003.640 ms58 ms70 ms32 ms17 %71 MiBok
8006.6100 ms128 ms190 ms67 ms32 %139 MiBok
12009.8175 ms235 ms308 ms168 ms62 %200 MiBok
160013277 ms385 ms460 ms265 ms79 %262 MiBok
240019.91.8 s2.5 s3 s1.7 s87 %400 MiBtoo slow

0.3.0: 2 CPUs, 2 GB

People onlineMessages/sPost p95Seen p95Seen p99Page p95Server CPU (avg)Memory (max)Result
500.512 ms15 ms17 ms8 ms1 %12 MiBok
100110 ms17 ms19 ms8 ms3 %21 MiBok
2001.611 ms24 ms27 ms10 ms6 %37 MiBok
4003.718 ms38 ms47 ms16 ms20 %69 MiBok
8006.446 ms63 ms81 ms31 ms44 %134 MiBok
120010.362 ms84 ms123 ms65 ms80 %199 MiBok
160013.1106 ms147 ms194 ms108 ms106 %263 MiBok
240021.1259 ms350 ms418 ms256 ms162 %394 MiBok
320025.61.3 s1.7 s2.3 s1.3 s163 %528 MiBtoo slow

Now: ½ CPU, 512 MB

People onlineMessages/sPost p95Seen p95Seen p99Page p95Server CPU (avg)Memory (max)Result
8006.518 ms22 ms31 ms13 ms11 %19 MiBok
160013.228 ms36 ms74 ms23 ms25 %36 MiBok
320026.472 ms97 ms412 ms75 ms38 %65 MiBok
480038.8123 ms160 ms262 ms96 ms43 %94 MiBok
640052.910.5 s9.4 s12.3 s8 s50 %319 MiBtoo slow

Now: 1 CPU, 1 GB

People onlineMessages/sPost p95Seen p95Seen p99Page p95Server CPU (avg)Memory (max)Result
8006.115 ms19 ms27 ms10 ms11 %19 MiBok
160013.821 ms26 ms35 ms15 ms24 %34 MiBok
320027.420 ms27 ms43 ms15 ms35 %61 MiBok
480040.420 ms26 ms36 ms17 ms46 %88 MiBok
640053.858 ms71 ms176 ms45 ms74 %125 MiBok
960080.8380 ms471 ms600 ms272 ms88 %193 MiBok
12800105.78.2 s10 s11.5 s6.6 s95 %544 MiBtoo slow

Now: 2 CPUs, 2 GB

People onlineMessages/sPost p95Seen p95Seen p99Page p95Server CPU (avg)Memory (max)Result
8007.118 ms20 ms26 ms13 ms12 %20 MiBok
160013.818 ms21 ms29 ms15 ms29 %33 MiBok
320026.919 ms24 ms37 ms18 ms51 %61 MiBok
480039.318 ms22 ms43 ms13 ms61 %87 MiBok
640052.223 ms29 ms54 ms17 ms86 %119 MiBok
960079.579 ms94 ms345 ms58 ms154 %197 MiBok
12800105.8285 ms340 ms430 ms204 ms168 %255 MiBok