What Sentry's self-hosted RAM warning taught us about building a smaller ingest path
On this pageShowHide 1. The warning is correct 2. Four failure modes 3. Scope I refused 4. Two containers 5. Footprint receipt 6. Spike valve defaults 7. What this is not 8. Pin and compose up 9. Questions
If you self-host on a small VPS and only need the next grouped exception, Sentry's RAM warning means the official install is a full suite. That suite is the undesired alternative. Epure is two containers, Rust plus PostgreSQL 16, a DSN swap, and Apache 2.0. It does not ship tracing, replay, or profiling, and it is not 100% compatible.
You are the person shipping the product and the Compose file. People quote the RAM floor because official self-hosted Sentry is errors plus traces, replay, profiling, and the brokers under them: dozens of services on a machine that feels wrong on a small VPS. These are design notes on the smaller job.
Proof in this note: a dated `docker stats` receipt (2026-09-23, 2 vCPU / 769 MiB Linux VPS) for an error-tracking ingest path. Bias disclosed: Epure first-party docs and that measurement describe Epure. Sentry, GlitchTip, and Bugsink public docs describe their products. This note is not an alternatives roster. The same refusal sits on Welcome.
Install shape: Installation. First event: Quickstart. Acceptance: Verify. SDK packages: Platforms. Related notes, each with its own job: Two-container error tracking, Spike valve flood, Sentry SDK compatible. Peers: Epure vs Sentry, Epure vs GlitchTip, Epure vs Bugsink.
The warning is correct
Sentry's self-hosted docs publish a high RAM floor because that product includes tracing, replay, profiling, and the services under them. As of 2026-09, the floor Epure's comparisons cite is 16 GB RAM plus 16 GB swap and 20+ containers (Sentry self-hosted). If that suite is how you debug, plan for that machine. The warning is correct for the product Sentry is.
A different job is narrower. When production throws, show a grouped issue with a stack you can read, and keep a crash loop from melting the box or the invoice. The rest of this note is that job.
Four failure modes
On a small VPS the failures rhyme. The official install is a serious ops project, hosted plans meter every duplicate, some Sentry-wire tools still want extra services, and a source-available license is a different contract from Apache 2.0.
- Install gravity. Official self-hosted Sentry is a serious ops project. Fine when that is the team's job. Brutal when one person ships the SaaS and the Compose file.
- Bill shock on the hosted side. Event-metered plans charge every duplicate. One bad deploy overnight is an incident and an overage. The crash is the same crash. The invoice is a second incident.
- Compatible tools that still want a fleet. Some Sentry-wire alternatives stay closer to a platform: extra services, broader scope. Useful when you want that scope. Heavier than exceptions only.
- License friction. Source-available shields can be a fine fit. They are a different license from Apache 2.0. Fork and procurement questions show up in threads because the license is the product.
- You quote Sentry's self-hosted RAM floor because you do not want that suite on a small VPS.
- The job is grouped exceptions, a readable stack, and a crash loop that does not store every duplicate body.
- You want Apache 2.0, PostgreSQL 16, and two Compose services, with sample rates for traces, replay, and profiles at 0.
- You need tracing, replay, or profiling: stay on Sentry (Epure vs Sentry).
- You are counting Compose services: Two-container error tracking.
- You are shopping published RAM floors: Self-hosted under 512 MB.
- One SQLite container already fits: Epure vs Bugsink. MIT Django: Epure vs GlitchTip.
GlitchTip, Bugsink, Telebugs, and Sentry exist because the need is real. GlitchTip showed that a DSN swap plus a smaller stack wins installs. Bugsink's problem essays did more for this category than bare launch posts. This note stands on that pattern.
Scope I refused
Scope is a product feature. Epure does not ship distributed tracing, session replay, continuous profiling, generic log ingestion, or native mobile symbolication. Redis, Kafka, and ClickHouse are not required dependencies. Epure is not 100% Sentry protocol compatible. If those pieces are how you debug, stay on Sentry or a fuller alternative.
Explicit negative scope (Welcome / API)
Distributed tracing
EpureDoes not ship
Session replay
EpureDoes not ship
Continuous profiling
EpureDoes not ship
Generic log ingestion
EpureDoes not ship
iOS / Android symbolication
EpureOut of scope (JS/TS .map only)
Redis, Kafka, ClickHouse
EpureNot required dependencies
Sentry protocol parity
EpureNot 100% compatible
Transaction, replay, profile items
EpureDiscarded on ingest
| Dimension | Epure | | ---------------------------------- | ------------------------------ | | Distributed tracing | Does not ship | | Session replay | Does not ship | | Continuous profiling | Does not ship | | Generic log ingestion | Does not ship | | iOS / Android symbolication | Out of scope (JS/TS .map only) | | Redis, Kafka, ClickHouse | Not required dependencies | | Sentry protocol parity | Not 100% compatible | | Transaction, replay, profile items | Discarded on ingest |
First-party. Welcome and the API docs are the source. This table is the refusal, not a feature checklist for Sentry Cloud.
Two containers
The Compose path that survived a small VPS is two services. One Rust binary does ingest, the API, and the embedded dashboard. PostgreSQL 16 stores issues and events, with row-level security isolating orgs. There is no separate worker container and no Redis in the OSS compose.
Keep the official Sentry SDK and change the DSN. Set traces, replay, and profiles sample rates to 0 when the SDK exposes them. Compatibility varies by language and version. Quickstart CI pins are `@sentry/browser@7.120.0` and `@sentry/node@7.120.0`. Other runtimes are on Platforms. The matrix is the substitute for a works-everywhere claim. Wire detail lives in Sentry SDK compatible.
Pinned laptop Compose images (Installation defaults, tag pinned)
epure
Imageghcr.io/epure-sh/epure:v0.1.1
Portshost 8080 to container 8080
postgres
Imagepostgres:16-alpine
Portshost 5433 to container 5432
| Dimension | Image | Ports | | --------- | ----------------------------- | --------------------------- | | epure | ghcr.io/epure-sh/epure:v0.1.1 | host 8080 to container 8080 | | postgres | postgres:16-alpine | host 5433 to container 5432 |
Set EPURE\_IMAGE to the pinned tag. No .env required for localhost. Production uses the overlay under deploy/ and real passwords. Service-count narrative: the two-container guide.
Footprint receipt
As of 2026-09-23, idle classic Compose on a 2 vCPU / 769 MiB Linux VPS (Alibaba Cloud) measured about 5 MiB RSS for Epure and about 48 MiB RSS for Postgres with `docker stats`, about 53 MiB combined. A short store-ingest burst on that same host, about 280-330 requests per second, kept Epure under about 12 MiB RSS. Postgres was the heavier process.
Host OS and the Docker runtime move these numbers. An earlier idle on Docker Desktop, about 82 MiB combined on 2026-09-12, is a different machine. That figure is the one quoted on Self-hosted under 512 MB. Neither row is a vendor minimum. Re-verify with `docker stats` on the box you pay for. The point is a dated method you can argue with.
Dated docker stats receipts (do not average)
Idle, 2026-09-23
Host2 vCPU / 769 MiB Linux VPS, Alibaba Cloud
RSSEpure about 5 MiB, Postgres about 48 MiB, about 53 MiB combined
Burst, same host
HostShort store-ingest, about 280-330 req/s
RSSEpure under about 12 MiB; Postgres heavier
Idle, 2026-09-12
HostDocker Desktop (other guide)
RSSAbout 82 MiB combined, app + Postgres
| Dimension | Host | RSS | | ---------------- | ----------------------------------------- | --------------------------------------------------------------- | | Idle, 2026-09-23 | 2 vCPU / 769 MiB Linux VPS, Alibaba Cloud | Epure about 5 MiB, Postgres about 48 MiB, about 53 MiB combined | | Burst, same host | Short store-ingest, about 280-330 req/s | Epure under about 12 MiB; Postgres heavier | | Idle, 2026-09-12 | Docker Desktop (other guide) | About 82 MiB combined, app + Postgres |
First-party docker stats. The 2026-09-23 rows are this note. The 2026-09-12 row is the 512 MB guide. Re-measure before you quote a floor.
Spike valve defaults
A crash loop should raise the count without storing every duplicate body. Documented defaults in API Errors: about 100 raw events per minute per fingerprint (HTTP 202, counter rises, excess bodies drop), a project cap of 5000 events per hour (then HTTP 403 `ingest_cap_exceeded`), and a 2 MB body limit (HTTP 413 `payload_too_large`). Those knobs may move before 1.0. Flood behavior is its own note: Spike valve flood.
Cloud soft-samples on the same idea so a loop does not become an overage story. Cloud is optional. The self-host valve runs on the two-container stack without it.
What this is not
Epure is not a free clone of Sentry. A 20+ container install does not become two containers with the same features. Transaction, replay, and profiling items are discarded on ingest. If replay or APM is the daily loop, Sentry remains the better fit (Epure vs Sentry).
Peers already hold honest corners of this market. Bugsink's one-container SQLite-first path is a real win for laptop and tiny-VM ops (Epure vs Bugsink). GlitchTip's MIT Django stack is real (Epure vs GlitchTip). Epure's bet is narrower: error tracking, Rust plus Postgres, Apache 2.0, a dated idle RSS, a spike valve, two containers.
Design contrast, not a buying roster (as of 2026-09)
Containers
Sentry self-host20+
GlitchTipAbout 4
Bugsink1
Epure2
License
Sentry self-hostFSL
GlitchTipMIT
BugsinkPolyform Shield
EpureApache 2.0
Default store
Sentry self-hostPostgres, heavy stack
GlitchTipPostgres
BugsinkSQLite (Postgres optional)
EpurePostgreSQL 16
Daily job
Sentry self-hostFull suite
GlitchTipDSN-swap errors, smaller stack
BugsinkDSN-swap errors, one container
EpureExceptions only
| Dimension | Sentry self-host | GlitchTip | Bugsink | Epure | | ------------- | --------------------- | ------------------------------ | ------------------------------ | --------------- | | Containers | 20+ | About 4 | 1 | 2 | | License | FSL | MIT | Polyform Shield | Apache 2.0 | | Default store | Postgres, heavy stack | Postgres | SQLite (Postgres optional) | PostgreSQL 16 | | Daily job | Full suite | DSN-swap errors, smaller stack | DSN-swap errors, one container | Exceptions only |
First-party bias on the Epure column. Sentry, GlitchTip, and Bugsink cells follow public docs already used on Epure comparison pages, as of 2026-09. RAM floors for that roster live on the 512 MB guide.
The tracker is Apache 2.0. There is no separate `ee/` tree. Self-host license cost is $0. Managed Cloud (Pro $24, Plus $79) is a separate product. It is not the gate on the OSS binary, and this note does not require it.
Triage starts at the issue list. Resolve and ignore from the keyboard (`e` and `i` on Issues). Markdown export (`Ctrl+Shift+C`) copies a crash when you want it in an editor. That is the control plane.
Pin and compose up
If you want to try the path, pin the image, boot the two containers, and hit health before you point a DSN. Full steps: Installation and Quickstart.
`EPURE_IMAGE=ghcr.io/epure-sh/epure:v0.1.1 docker compose up -d`
`curl -sS http://localhost:8080/health`
Expect `{"status":"ok"}`. Open `:8080`, create a project, paste the DSN into an official Sentry SDK with traces, replay, and profiles sample rates at 0. Confirm with Verify. Default host ports are 8080 and 5433. No `.env` is required for localhost. For any host that is not localhost, use the prod overlay under `deploy/` and real passwords. Laptop compose refuses example passwords once `EPURE_PUBLIC_URL` is a real hostname.
Repo, if you already decided to try compose: github.com/epure-sh/epure.
Use these notes if
Read something else if
Deep links: Quickstart | Verify | Installation | Platforms.
FAQ
Questions
What does Sentry's self-hosted RAM warning mean?
It means the official self-host is errors plus tracing, replay, and profiling, not a single error tracker. As of 2026-09, Epure's comparisons cite Sentry's published floor of 16 GB RAM plus 16 GB swap and 20+ containers. If you want tracing, replay, and profiling on your own metal, plan for that footprint. If you only want grouped exceptions, that suite is the wrong machine.
What idle RSS did the 2026-09-23 docker stats show?
On a 2 vCPU / 769 MiB Linux VPS (Alibaba Cloud), classic Compose at idle measured about 5 MiB RSS for Epure and about 48 MiB RSS for Postgres, about 53 MiB combined. A short store-ingest burst on that host (about 280-330 requests per second) kept Epure under about 12 MiB RSS. A different Docker Desktop idle on 2026-09-12 was about 82 MiB combined. Re-measure on your box. Neither number is a vendor minimum.
Is Epure 100% Sentry compatible?
No. Epure accepts official Sentry SDK traffic for an exception subset after a DSN swap. It is not 100% Sentry protocol compatible. Distributed tracing, session replay, continuous profiling, generic logs, and native mobile symbolication do not ship. Transaction, replay, and profiling items are discarded on ingest.
Which containers does Epure Compose start?
Two: `ghcr.io/epure-sh/epure:v0.1.1` (pin with EPURE\_IMAGE) and `postgres:16-alpine`. Laptop defaults publish host port 8080 for the app and 5433 for Postgres. There is no Redis, Kafka, ClickHouse, or separate worker in that compose file. Steps: Installation and Quickstart.
How is this different from GlitchTip or Bugsink?
If GlitchTip already fits, keep it. Same for Bugsink when one container and their license fit. GlitchTip is MIT, Django, about four containers, Postgres. Bugsink is one container, SQLite by default, Polyform Shield. Epure is Apache 2.0, Rust plus PostgreSQL 16, two containers, a spike valve, and a dated idle RSS. Same basic job: exceptions over a DSN. Different ops contract.
What happens when one crash loops?
The in-process spike valve defaults to about 100 raw events per minute per fingerprint. Saturated fingerprints still return HTTP 202, the issue counter rises, and excess duplicate bodies drop. The separate project cap defaults to 5000 events per hour, then HTTP 403 ingest\_cap\_exceeded. Bodies over 2 MB return HTTP 413 payload\_too\_large. Exact knobs are in the API errors docs and may move before 1.0.
How do I pin the image and check health?
From the product repo, set EPURE\_IMAGE=ghcr.io/epure-sh/epure:v0.1.1 and run docker compose up -d. Then curl -sS http://localhost:8080/health and expect {"status":"ok"}. Create a project and point an official Sentry SDK at the DSN with traces, replay, and profiles sample rates at 0. No .env is required for localhost. A real hostname needs the prod overlay and real passwords.