Sentry-compatible error tracking in a single Go binary. 4MB of RAM. Zero cloud dependencies. Your errors, your server.
CONTAINER CPU % MEM USAGE / LIMIT
gosnag-gosnag-1 0.00% 4.4MiB / 256MiB
gosnag-db-1 0.00% 51.6MiB / 256MiB Built for teams that want error visibility without the complexity or cost of a full observability platform.
Drop-in replacement for Sentry. Use the official SDKs — PHP, JavaScript, Python, Go, Ruby — just point the DSN at your GoSnag instance.
Email and Slack alerts with per-alert level filters and regex title matching. Get notified about what matters, silence the noise.
Resolve, snooze (by time or event count), ignore, assign. Cooldown periods prevent resolved issues from immediately reopening.
Errors, Warnings, and Info — each with independent counts, filters, and collapsible sidebar sections. Info-level issues skip the resolve/ignore workflow.
Google Identity Services authentication out of the box. Role-based access: admin and viewer roles with invite-based onboarding.
The React SPA is embedded into the Go binary at build time. One Docker container, one port, done. No nginx, no reverse proxy config.
Three components. One server. That's the entire production topology.
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.
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.
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.
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.
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.
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.
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.
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.
Honest constraints. GoSnag is a focused tool, not a platform. These are deliberate tradeoffs, not a roadmap.
Minified stack traces stay minified. No source map upload or processing pipeline.
Release data is stored but there are no release health dashboards or deploy tracking.
Transaction and span data from SDKs is not processed. You can route performance signals as warning-level messages via beforeSendTransaction.
No horizontal scaling, no event buffering queue. Designed for small-to-medium teams, not thousands of events per second.
No GitHub, GitLab, Jira, or PagerDuty integrations. Alerts go to email or Slack webhooks.
Filter by level, status, and assignment. No full-text search across event payloads or breadcrumbs.
git clone https://github.com/darkspock/gosnag.git
cd gosnag
cp .env.example .env
# Edit .env with your Google OAuth credentials and DB password docker compose up --build -d 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';" // Any Sentry SDK — PHP, JS, Python, Go, Ruby...
Sentry.init({
dsn: "https://<key>@your-server.com/<project-id>",
});