TL;DR: The free tier cap isn't an inconvenience — it's a trap. A mid-traffic side project running into a bad deploy can exhaust Sentry's hosted event quota within the first hour of the incident.
📖 Reading time: ~16 min
What's in this article
- Why Sentry's Hosted Version Becomes a Problem at Scale
- The 5 Tools: Quick Comparison Before the Detail
- GlitchTip: The Closest Drop-In for Sentry SDK Users
- Errbit: For Teams Running Ruby or Wanting Airbrake Compatibility
- Signoz: When You Need Traces and Metrics Alongside Errors
- Highlight.io: Session Replay Plus Errors in One Self-Hosted Stack
- Picking the Right Tool for Your Setup
Why Sentry's Hosted Version Becomes a Problem at Scale
The free tier cap isn't an inconvenience — it's a trap. A mid-traffic side project running into a bad deploy can exhaust Sentry's hosted event quota within the first hour of the incident. That's the exact window where you need error visibility most, and instead you're watching the dashboard show zeros while your users are hitting 500s. Upgrading mid-incident isn't a workflow. Paying for headroom you don't normally need just to survive the occasional spike is a recurring tax that compounds across multiple projects.
Self-hosting the official Sentry distribution solves the quota problem but trades it for infrastructure complexity that's wildly out of proportion to the task. The docker-compose manifest ships with over 20 services — Kafka, ClickHouse, Redis, Celery workers, Snuba, the Relay ingestion pipeline, and more. The install script refuses to proceed with less than 3 GB of RAM allocated, and that's before you've ingested a single event. Running this on a shared VPS or home-lab machine that already hosts other workloads means you're either constantly fighting OOM kills or dedicating a node exclusively to error tracking. That's a hard justification to make when the application generating the errors is itself a small project.
The core mismatch is what developers actually want from a self-hosted error tracker versus what Sentry's architecture was built to deliver. Source maps, readable stack traces, release tagging, environment filters, basic alerting — that's the real list. Kafka exists in the official stack because Sentry processes billions of events per month across their SaaS offering. That throughput requirement drives architectural decisions that then get inherited by anyone self-hosting, regardless of whether they're handling a hundred events a day or a million. You end up running a small data platform to power what should be a single-purpose tool.
For this comparison, "lightweight" means something specific and testable:
- Deployable as a single Docker container or a Compose stack with no more than three or four services
- Under 1 GB RAM at idle — low enough to share a 2 GB VPS with a running application
- Postgres or SQLite as the only stateful dependency — no Kafka, no ClickHouse, no separate queue infrastructure
- Functional source map support and structured stack traces — not just raw JSON event dumps
That constraint set cuts out a lot of candidates. Several "Sentry alternatives" in blog posts still pull in Redis plus a task queue plus a separate ingestion service the moment you enable any real feature. The ones worth running on a single box are the ones that made deliberate architectural decisions to stay small — and those decisions show up immediately in the Compose file line count and the docker stats output after a day of running.
The 5 Tools: Quick Comparison Before the Detail
The most useful thing to know upfront: these five tools split cleanly into two categories that serve different operators. Two of them — GlitchTip and Errbit — exist specifically to be Sentry-compatible backends. Point your existing DSN at them and you're done. The other three — SigNoz, Highlight.io, and Baselime (now AWS-native) — are broader observability stacks where error tracking is one tab among several. Picking the wrong category means either ripping out instrumentation you don't need to touch, or paying for a full observability platform when you just want a crash log.
Sentry SDK compatibility is the deciding filter for most self-hosters. If your app already ships @sentry/node, sentry-python, or the browser @sentry/browser package, a DSN-compatible backend costs you zero instrumentation rework — you change one environment variable. If you pick a non-compatible platform, you're re-instrumenting every service, which is a real cost on a multi-service setup. Don't let a feature list override that operational reality.
Here's the comparison across the dimensions that actually matter when you're planning a self-hosted deployment:
Tool Min RAM Backing Store Sentry SDK Compat Source Maps Biggest Dealbreaker
----------- -------- ------------------- ----------------- ----------- -------------------------------------------
GlitchTip 512 MB Postgres + Redis Yes (drop-in DSN) Yes Grouping logic lags behind Sentry's
Errbit 256 MB MongoDB Yes (drop-in DSN) No native No timeline view; Ruby-era UX
SigNoz 4 GB+ ClickHouse No Yes Heavy stack; ClickHouse eats disk fast
Highlight.io 2 GB+ Postgres + ClickHouse No Yes Requires full session replay pipeline
Baselime — AWS (not self-hosted) No Yes Not actually self-hostable; AWS-only
A few numbers worth expanding on: SigNoz's ClickHouse dependency is the operational weight you're accepting. ClickHouse is a columnar store optimized for high-throughput append workloads — great for traces and metrics at scale, but it will consume disk at a rate that surprises operators coming from Postgres-only stacks. Expect to set aggressive TTL policies on your spans table within the first week or you'll watch a modest event volume balloon into tens of gigabytes. GlitchTip's 512 MB floor is real and reproducible on a $6/month VPS, making it the only option here that doesn't demand a dedicated box. Errbit's 256 MB claim holds only if you keep MongoDB lean — in practice, with a few weeks of error history, you're looking at 1 GB+ for the Mongo data directory alone.
Source map support is the other sharp dividing line, especially for frontend-heavy teams. GlitchTip handles uploaded source maps through its release artifact API, which is compatible with the standard sentry-cli upload workflow. Errbit has no built-in source map processing — stack traces from minified JS land in your inbox exactly as mangled as they came in, which makes it a poor fit for any project shipping a bundled frontend. If you're also evaluating AI-assisted debugging tooling alongside these, see our guide on AI Coding Tools in 2026: Cloud Copilots vs Local Models for the broader context on where automated analysis fits into an error triage workflow.
GlitchTip: The Closest Drop-In for Sentry SDK Users
The migration story is almost suspiciously simple: swap one URL. GlitchTip uses the exact same DSN format as Sentry, which means the difference between pointing at sentry.io and pointing at your own box is literally a hostname change. SENTRY_DSN=https://key@sentry.io/123 becomes SENTRY_DSN=https://key@your-glitchtip.host/123 — no SDK version bump, no new client library, no configuration schema to learn. If you're already running Sentry SDKs across a handful of services, GlitchTip is the only self-hosted option where you aren't also rewriting instrumentation.
The full stack is a single Django app, Postgres, and Redis. That's it. A working docker-compose.yml stays under 50 lines with room to spare, and after the containers warm up, idle RAM hovers in the 200–300 MB range total — not per service. The minimum viable setup needs three environment variables before docker compose up -d will get you anywhere useful:
# .env — minimum required before first boot
SECRET_KEY=replace-with-a-long-random-string
DATABASE_URL=postgres://glitchtip:pass@db:5432/glitchtip
GLITCHTIP_DOMAIN=https://errors.yourdomain.com
The non-obvious one to set immediately — before you ingest a single event — is GLITCHTIP_MAX_EVENT_LIFE_DAYS. GlitchTip has no automatic event expiry enabled out of the box. On a busy application this means your Postgres volume grows without any ceiling, and on a cheap VPS with 20–40 GB of disk you'll eventually hit a full-disk condition that takes the whole container stack down silently. The fix is a one-liner in your env file, but the docs don't surface it prominently:
# add to .env — without this, Postgres grows unbounded
GLITCHTIP_MAX_EVENT_LIFE_DAYS=90
Performance monitoring exists — GlitchTip does accept transaction data from Sentry SDKs — but treat it as a checkbox, not a feature. You get basic transaction lists and error-rate summaries. What you don't get: session replay, profiling, span-level flame graphs, or anything from the Sentry performance tab that you'd actually open during an incident. If your team uses Sentry primarily to catch and group unhandled exceptions, GlitchTip covers that workload cleanly. If someone on your team has Sentry's profiler tab bookmarked, they'll notice the gap within a day.
Errbit: For Teams Running Ruby or Wanting Airbrake Compatibility
The first thing to understand about Errbit is that it does not speak Sentry's protocol. It implements the Airbrake v2 API — which means you're reaching for the airbrake gem or airbrake-js, not any Sentry SDK. That's a hard architectural constraint, not something you toggle in a config file. If your codebase already has Sentry SDK calls scattered through it, Errbit is not a drop-in swap. But if you're on a legacy Rails monolith that's been using the Airbrake notifier for years, Errbit is essentially a self-hosted backend that already matches your client setup exactly.
The Docker compose setup is straightforward: the official errbit/errbit image paired with a mongo:6 container. No Redis dependency, which keeps the stack simpler than most alternatives. The real resource cost is MongoDB — expect 300–500 MB resident memory on a quiet instance just from the Mongo process sitting there. That's not a dealbreaker, but it's the number to check against your VPS tier before committing.
services:
errbit:
image: errbit/errbit:latest
environment:
- RACK_ENV=production
- MONGO_URL=mongodb://mongo:27017/errbit
- SECRET_KEY_BASE=changeme_generate_with_openssl_rand
- EMAIL_FROM=errors@yourdomain.com
ports:
- "8080:8080"
depends_on:
- mongo
mongo:
image: mongo:6
volumes:
- errbit_mongo:/data/db
# no auth config here — add --auth and a keyfile for production
volumes:
errbit_mongo:
Error grouping uses backtrace fingerprinting, which handles Ruby and Rails stack traces well — the frames are stable, human-readable, and consistent between deploys as long as your gem versions don't churn. Where this breaks down is minified JavaScript. Without source maps pre-processed server-side before errors arrive, Errbit groups JS errors against mangled frame addresses that change every build. You get a new "unique" error on every deploy rather than a deduplicated stream. If JavaScript error tracking is a significant part of your needs, that friction is real and not easily patched around.
The honest best-fit profile for Errbit: a Rails monolith already wired to the Airbrake notifier, an infrastructure where MongoDB is already running for something else (so the memory cost is already paid), and a team that doesn't need Slack-level integrations or sophisticated alerting rules. It's minimal, it's stable, and it doesn't require you to retrain anyone who's been using Airbrake. Outside that context — especially if you're running a polyglot stack or need strong JavaScript support — the API lock-in will cost you more than the self-hosting saves.
Signoz: When You Need Traces and Metrics Alongside Errors
The biggest conceptual shift with SigNoz isn't the UI or the query language — it's that errors don't arrive via a Sentry DSN at all. SigNoz is OpenTelemetry-native, which means exceptions surface as OTel log and exception events flowing through the collector pipeline. If you've been using @sentry/node or any Sentry SDK, swapping to SigNoz means ripping that out and replacing it with the OTel SDK stack. That's not a config change; it's a real migration. Expect to touch every service that currently initializes Sentry, replace the SDK initialization, and wire up the exporter endpoint.
# Replacing Sentry init with OTel in a Node.js service
# Before (Sentry):
# Sentry.init({ dsn: "https://...", tracesSampleRate: 1.0 });
# After (OTel):
npm install @opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-otlp-grpc
// instrumentation.ts — runs before anything else via --require
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
const sdk = new NodeSDK({
// Point at your SigNoz OTel collector, not a Sentry DSN
traceExporter: new OTLPTraceExporter({
url: 'grpc://your-signoz-host:4317',
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
// Unhandled exceptions now appear as span events in SigNoz,
// not as Sentry issues — the grouping model is completely different
The Docker Compose install is where "lightweight" gets complicated. The official stack pulls in ClickHouse, a query service, the OTel collector, an alertmanager, and several supporting containers — the total is typically 8+ containers. SigNoz's own docs recommend a 4 GB RAM floor just for the stack itself. On a shared 4 GB VPS that's already running Nginx, Postgres, and your app, SigNoz will win the memory contest and everything else will lose. ClickHouse under indexing load is particularly aggressive about buffer allocation. This isn't a dealbreaker — it just means SigNoz belongs on a dedicated node or a home-lab machine where you have 8+ GB free to hand it.
# Checking what the Compose stack actually pulls
git clone https://github.com/SigNoz/signoz.git
cd signoz/deploy/docker/clickhouse-setup
docker compose config --services
# Expect: clickhouse, query-service, frontend, alertmanager,
# otel-collector, otel-collector-metrics, logspout, ...
# Count them before you commit to a VPS tier
What you actually gain over simpler alternatives like GlitchTip is real correlated observability: a single failing request shows you the exception, the full distributed trace, the service map hop where latency spiked, and infrastructure metrics on the same timeline. That correlation is the feature. When an error fires at 2am, you're not manually cross-referencing three dashboards — the trace is attached to the exception event. The query interface also lets you slice arbitrary log fields rather than just exception type and message, which matters once you're past basic error grouping and want to understand patterns across deployments or regions.
The operational cost for that capability is real. When the stack fails to start cleanly, you're not reading one log — you're reading ClickHouse startup output and the OTel collector logs simultaneously to figure out which dependency failed to become healthy first. A common failure mode is ClickHouse not being ready when the query service attempts its initial schema migration; the fix is usually just waiting and restarting the query service container, but figuring that out the first time takes longer than it should. Use SigNoz when you have spare hardware capacity and you've outgrown pure error tracking — when you need traces to explain why errors happen, not just that they happened.
Highlight.io: Session Replay Plus Errors in One Self-Hosted Stack
Session replay baked into the same error pipeline is the actual differentiator here — not in a marketing sense, but in a debugging sense. When a user hits a TypeError: Cannot read properties of undefined in your React app, you don't just get a stack trace; you get an rrweb recording of exactly what they clicked, scrolled, and typed before the crash. Correlating errors to sessions without a separate tool like LogRocket or FullStory is the whole reason to look at Highlight.io seriously.
The self-hosted stack is honest about its complexity. The Docker Compose setup pulls in Postgres (session metadata, user data), ClickHouse (event storage and aggregation), and either MinIO or an S3-compatible store for the raw replay chunks. That's not bloat for the sake of it — ClickHouse is genuinely the right engine for time-series event queries at replay scale, and object storage is the only sane place to put binary replay data. But the practical consequence is that you need 6+ GB RAM as a floor before your actual application runs. ClickHouse alone wants 2-4 GB to behave, MinIO needs headroom, and the Highlight app containers add more on top. If you're thinking about slotting this onto a $6/mo VPS, the math doesn't work. This belongs on a home-lab box or a cloud instance with at least 8 GB dedicated to the observability stack.
# The core of the self-hosted compose — what you're actually committing to:
services:
postgres:
image: postgres:16
environment:
POSTGRES_PASSWORD: highlight
clickhouse:
image: clickhouse/clickhouse-server:23.12
# expects ~2GB RAM minimum under real query load
ulimits:
nofile:
soft: 262144
hard: 262144
minio:
image: minio/minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: highlight
MINIO_ROOT_PASSWORD: changethis
highlight:
image: ghcr.io/highlight/highlight:latest
depends_on: [postgres, clickhouse, minio]
The SDK situation is where migration cost becomes real. Highlight ships @highlight-run/node for the backend and highlight.run for the browser — neither is a drop-in for the Sentry SDK. There's no Sentry-compatible DSN endpoint, no captureException alias that just works. You're doing a proper SDK swap: remove @sentry/node, install @highlight-run/node, update your error boundary wrappers, update your environment config, and then learn a new dashboard. For a mature app with Sentry wired into a dozen places, that's a half-day minimum, not a config swap. The upside is the product you get is genuinely richer — network request timelines, console logs, and the replay are all first-class in the same view.
The honest use-case boundary: if your errors are predominantly backend — Node.js workers, API services, queue consumers — Highlight's resource overhead is hard to justify. GlitchTip or Signoz will give you error aggregation for a fraction of the RAM. Highlight earns its place specifically when you're debugging frontend-triggered failures where the stack trace alone doesn't tell you enough. A user reports a blank screen on checkout; the replay shows them resizing the browser window at a specific breakpoint right before the React hydration error fires. That's the scenario where six gigabytes of supporting infrastructure actually pays for itself.
Picking the Right Tool for Your Setup
The honest answer most "comparison" posts dodge: for a solo operator who just wants Sentry-compatible error tracking without babysitting infrastructure, GlitchTip on a 1 GB VPS with Postgres is the default. Drop in your existing Sentry SDK, set one environment variable, put Nginx in front, and you're done. The config that actually matters:
# docker-compose env block — the one variable most people miss
GLITCHTIP_MAX_EVENT_LIFE_DAYS=90 # without this, the DB grows unbounded
SECRET_KEY=your-random-64-char-string
DATABASE_URL=postgres://glitchtip:pass@db:5432/glitchtip
EMAIL_URL=smtp://user:pass@smtp.yourhost.com:587
Nginx in front handles TLS termination, and Certbot handles renewal. The entire ops surface is one Compose file and a cron for docker compose exec web python manage.py migrate after upgrades. A 1 GB VPS handles low-to-moderate error volumes without complaint — Postgres is the only datastore, so backups are a single pg_dump command. That simplicity is the point.
Two legitimate reasons to deviate from that default. If you're running a legacy Ruby app already wired to Airbrake, pick Errbit and accept MongoDB. Rewriting SDK calls across a mature Rails codebase to hit a different endpoint costs more than running Mongo ever will. MongoDB on a single node with a scheduled mongodump is not a complex ops burden — the friction of fighting SDK compatibility is. Conversely, if you've got a spare home-lab node with 8+ GB RAM and need traces plus metrics alongside errors, SigNoz is the correct answer. Instrument everything with OpenTelemetry from day one:
# Node.js OTel bootstrap — same collector config works for SigNoz today,
# any OTLP-compatible backend tomorrow
OTEL_EXPORTER_OTLP_ENDPOINT=http://signoz-otel-collector:4317
OTEL_SERVICE_NAME=my-api
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
The OTel abstraction means you're not locked to SigNoz — if you outgrow it or migrate, the instrumentation code doesn't change, only the collector endpoint does. That matters more than any feature SigNoz ships next quarter.
The one case where none of the above applies: frontend apps where session replay is a hard requirement. Highlight.io is the only self-hosted option that ships replay, error tracking, and logging as a single deployable stack. Building replay yourself on top of GlitchTip or Errbit means maintaining a separate rrweb pipeline, a storage layer for recordings, and a playback UI — that's a significant side project. Highlight.io requires a dedicated host with meaningful RAM headroom, but if replay is genuinely non-negotiable for debugging user-reported issues, the ops cost is justified and there's no real alternative in the self-hosted space.
Disclaimer: This article is for informational purposes only. The views and opinions expressed are those of the author(s) and do not necessarily reflect the official policy or position of Sonic Rocket or its affiliates. Always consult with a certified professional before making any financial or technical decisions based on this content.
Originally published on techdigestor.com. Follow for more developer-focused tooling reviews and productivity guides.
Top comments (0)