All posts

Sentry self-hosted: the ingest tax on a small VPS

Self-hosted Sentry 26.10.1 idled near 12.6 GiB across 53 containers. Official docs want 16 GB RAM. A 4–8 GB VPS does not carry this compose.

Written by NodeRings Inc.

NodeRings Inc. writes these notes. The company runs the marketplace and the agent that stays on the provider’s side of the hypervisor.

Self-hosted Sentry 26.10.1 from getsentry/self-hosted came up with 53 running containers and a docker stats sum of about 12901 MiB (~12.6 GiB) before anyone sent traffic. Sentry’s own minimum is 4 CPU cores, 16 GB RAM plus 16 GB swap, and 20 GB free disk. A quiet 4 GB or 8 GB VPS sits under that floor. Two hundred capture_exception calls through a local DSN completed on the client; the stack moved to about 12988 MiB afterward. Almost all of the bill is idle compose, with only a small bump from the first burst.

ReadingValue
Releaseself-hosted 26.10.1
Running containers53
Idle docker stats sum~12901 MiB (~12.6 GiB)
After 200 SDK exceptions~12988 MiB
Docs minimum RAM16 GB (+ 16 GB swap)
Bar chart comparing 2, 4, 8, and 16 GB VPS sizes against measured Sentry idle near 12.6 GiB.
Idle alone clears a small VPS. Docs start at 16 GB for a reason.

“Ingest tax” here means RAM and CPU the compose spends when events hit Relay and the Kafka consumers. That is separate from the SaaS error quota. On this lab the first 200 exceptions added roughly 87 MiB. You still needed ~13 GiB free before that.

Why the compose is so heavy

One box runs the web UI, workers, Relay, Kafka, ClickHouse, Snuba consumers, Redis, Postgres, symbolicator, nginx, and a pile of ingest/post-process services. That is the reference architecture for “feature-complete on one machine,” not a trimmed error sink. Search posts that imply 4–8 GB “works for a hobby Sentry” usually describe an older build, a trimmed compose, or optimism.

Install on a host that can actually hold it

VERSION=26.10.1
git clone https://github.com/getsentry/self-hosted.git
cd self-hosted
git checkout "$VERSION"
./install.sh --no-report-self-hosted-issues --skip-user-creation \
  --no-apply-automatic-config-updates
docker compose up --wait
# UI: http://127.0.0.1:9000/
docker compose run --rm web createuser --superuser --no-input \
  --email [email protected] --password 'choose-a-long-one'

Pin the release tag. Prefer loopback (or Tailscale) for :9000 until Caddy terminates TLS. This lab skipped the optional SeaweedFS/S3 nodestore bootstrap (Alpine apk/s3cmd could not reach the network from the container) and kept the default Postgres nodestore. Idle RAM was still ~13 GiB.

Terminal freeze of git checkout 26.10.1, install.sh flags, and docker compose up --wait.
Official install path. Budget the docs minimum before you start pulling images.

Idle: where the memory went

Container (top of docker stats)~MiB idle
taskworker1208
web900
attachments-consumer687
launchpad-taskworker509
metrics-consumer474
Several events/transactions/post-process workers~460 each
Kafka~419
ClickHouse~225
Many Snuba consumers~150–260 each
Relay~52
Stack sum~12901
Idle stats summary: 53 containers, 12901 MiB total, taskworker and web leading.
Dozens of mid-size consumers add up faster than one fat app.

Sending events (the cheap part of the tax)

Create an organization project and DSN (UI or sentry shell), then point an SDK at http://<key>@127.0.0.1:9000/<project_id>.

import sentry_sdk
from sentry_sdk import capture_exception, flush

sentry_sdk.init(dsn="http://[email protected]:9000/2", traces_sample_rate=0.0)
for i in range(200):
    try:
        raise RuntimeError(f"lab-ingest-{i}")
    except Exception as e:
        capture_exception(e)
flush(timeout=60)
Ingest checkResult
Events with IDs200 / 200
Stack before~12901 MiB
Stack after~12988 MiB
Relay~52 → ~73 MiB
createuser, DSN shape, and 200 capture_exception summary.
SDK path through Relay. Client flush returned IDs for all 200.
Before and after ingest RAM: about 87 MiB rise on a 12.6 GiB floor.
Burst cost is small next to the idle floor.

What to buy (or not)

SKU ideaHonest lean
2 / 4 / 8 GB VPSSkip self-hosted Sentry. SaaS or a lighter self-host tool.
16 GBMatches the documented floor; expect ~13 GiB idle on this shape.
32 GBCloser to Sentry’s comfort note for growth.
App VPS already fullKeep Sentry elsewhere; keep Sentry off the game/panel box.
SKU guidance: small VPS skip, 16 GB floor, 32 GB comfort.
Size from idle plus headroom, or stay on SaaS.
Skip thisWhat this lab did
Installing on 4–8 GB “to try”Measured ~13 GiB idle on a host that meets docs
Treating SaaS quotas as the self-host RAM billSeparated ingest MiB from the compose floor
Publishing :9000 on every interfaceUsed loopback for the UI/DSN
Assuming SeaweedFS nodestore is freeSkipped offline; Postgres nodestore still left a 13 GiB floor
Equating “containers healthy” with “fits my VPS”Summed docker stats

Installer floors and the errors-only escape hatch

getsentry/self-hosted still documents Docker Engine 19.03.6+, Compose 2.32.2+, and a full-stack floor of 4 CPU cores with 16 GB RAM plus 16 GB swap (32 GB recommended) and about 20 GB free disk. The installer hard-checks roughly 14 GB visible RAM and 4 CPUs for the default profile, plus SSE 4.2 for ClickHouse. Disk I/O dominates feel: the docs call out iowait above ~10% of CPU time as a sign the single machine cannot keep Kafka, ClickHouse, Postgres, and friends happy. Since 24.8.0, COMPOSE_PROFILES=errors-only drops traces, profiles, replays, crons, and user feedback and lowers the installer’s bar to about 2 CPUs and 7 GB RAM. Monthly CalVer upgrades expect downtime while ./install.sh migrates; skip listed hard-stop versions in order. Bind SENTRY_BIND to loopback and put TLS on Caddy in front, the same pattern as other heavy panels on this site.

FAQ

Can I trim the compose? Yes, in theory (drop profiling, uptime, some consumers). You are then maintaining a fork of the reference stack. This post measures the stock install people actually run.

GlitchTip / other light forks? Fine for tiny boxes when you accept a different product. This post is about upstream self-hosted Sentry.

Disk? Docs want 20 GB free for install. Images and volumes here ate far more than a 20 GB cloud volume once everything was pulled. Plan disk the same way you plan RAM.

Swap instead of RAM? Docs allow 16 GB RAM + 16 GB swap. Expect pain on disk-backed swap under Kafka/ClickHouse I/O. Prefer real RAM for anything you care about.

What to run on the VPS

If you still want the full product under your own roof, size a Compute Instance from the idle number: plan 16 GB minimum, prefer more, keep :9000 private behind Caddy, and re-check docker stats after a real traffic day. For a small app on a cheap VPS, pay SaaS or pick a lighter error tracker and spend the RAM on the app. Compose habits for smaller stacks live in Docker Compose on a VPS; for privacy analytics that fit 1 GB, see Plausible vs Umami on 1 GB.