Self-hosted error tracking

Catch every error.
Keep nothing else.

Sentry-compatible error tracking in a single Go binary. 4MB of RAM. Zero cloud dependencies. Your errors, your server.

docker stats
CONTAINER          CPU %     MEM USAGE / LIMIT
gosnag-gosnag-1    0.00%     4.4MiB / 256MiB
gosnag-db-1        0.00%     51.6MiB / 256MiB
4.4 MB RAM usage Go binary at idle
~12 MB Docker image Alpine-based
1 Binary Frontend embedded
$0 License cost MIT open source

Everything you need.
Nothing you don't.

Built for teams that want error visibility without the complexity or cost of a full observability platform.

{}

Sentry SDK Compatible

Drop-in replacement for Sentry. Use the official SDKs — PHP, JavaScript, Python, Go, Ruby — just point the DSN at your GoSnag instance.

!

Smart Alerting

Email and Slack alerts with per-alert level filters and regex title matching. Get notified about what matters, silence the noise.

#

Issue Triage

Resolve, snooze (by time or event count), ignore, assign. Cooldown periods prevent resolved issues from immediately reopening.

>_

Three-Tier Classification

Errors, Warnings, and Info — each with independent counts, filters, and collapsible sidebar sections. Info-level issues skip the resolve/ignore workflow.

&

Google SSO

Google Identity Services authentication out of the box. Role-based access: admin and viewer roles with invite-based onboarding.

~

Single Binary Deploy

The React SPA is embedded into the Go binary at build time. One Docker container, one port, done. No nginx, no reverse proxy config.

Opinionated simplicity

Three components. One server. That's the entire production topology.

Sentry SDK Any platform
/api/{id}/store
Go Binary Chi router + embedded SPA
4.4 MB RAM ~12 MB image
sqlc queries
PostgreSQL Single instance

Why Go?

Go compiles to a single static binary with no runtime dependencies. The garbage collector is tuned for low latency, not throughput — perfect for a request-response service that spends most of its time idle. Memory usage stays flat whether you have 10 or 10,000 issues.

Why embed the frontend?

Go's embed directive bakes the compiled React SPA into the binary. No separate web server, no static file hosting, no CORS configuration. The same binary that serves the API also serves the dashboard.

Why PostgreSQL?

It's the most reliable open-source database. The entire schema runs on standard SQL — no extensions, no exotic features. sqlc generates type-safe Go code from plain SQL queries, so there's no ORM layer to leak abstractions.

The t3.small thesis

GoSnag runs on a t3.small EC2 instance (2 vCPU, 2 GB RAM, $15/month) — with PostgreSQL on the same box. Here's why that matters.

01

Infrastructure cost

Sentry's self-hosted setup requires Kafka, Redis, Clickhouse, Snuba, multiple workers, and 16+ GB of RAM. GoSnag needs one server with 2 GB. For a team of 5-20 developers, the error volume doesn't justify the infrastructure.

02

Operational burden

Every component is a thing that can fail at 3 AM. GoSnag has two containers: the binary and PostgreSQL. Docker Compose. That's the entire runbook. Backup the database, update the image, done.

03

Cold start & recovery

The Go binary starts in milliseconds. After a deploy or crash, the service is accepting events before the load balancer's health check interval expires. No JVM warmup, no interpreter boot, no dependency tree to resolve.

04

Data sovereignty

Error payloads contain stack traces, request headers, user data, and environment variables. Running your own instance means this data never leaves your network. Compliance is trivial when there's no third party.

What GoSnag is not

Honest constraints. GoSnag is a focused tool, not a platform. These are deliberate tradeoffs, not a roadmap.

x

No Source Maps

Minified stack traces stay minified. No source map upload or processing pipeline.

x

No Release Tracking

Release data is stored but there are no release health dashboards or deploy tracking.

x

No Performance Monitoring

Transaction and span data from SDKs is not processed. You can route performance signals as warning-level messages via beforeSendTransaction.

x

Single Instance

No horizontal scaling, no event buffering queue. Designed for small-to-medium teams, not thousands of events per second.

x

No Integrations

No GitHub, GitLab, Jira, or PagerDuty integrations. Alerts go to email or Slack webhooks.

x

Basic Search

Filter by level, status, and assignment. No full-text search across event payloads or breadcrumbs.

Running in 60 seconds

1

Clone and configure

git clone https://github.com/darkspock/gosnag.git
cd gosnag
cp .env.example .env
# Edit .env with your Google OAuth credentials and DB password
2

Start with Docker Compose

docker compose up --build -d
3

Create admin user

The first user needs to be promoted to admin via the database. After that, admins can invite other users from the UI.

# Local Docker setup
make admin EMAIL=you@example.com

# Or run the SQL directly
docker compose exec db psql -U gosnag -c \
  "INSERT INTO users (id, email, name, role, created_at, updated_at)
   VALUES (gen_random_uuid(), 'you@example.com', 'you@example.com',
   'admin', now(), now())
   ON CONFLICT (email) DO UPDATE SET role = 'admin';"
4

Point your Sentry SDK

// Any Sentry SDK — PHP, JS, Python, Go, Ruby...
Sentry.init({
dsn: "https://<key>@your-server.com/<project-id>",
});

Your errors deserve a home
that doesn't cost $29/month per seat.