In active development · MIT
Replace Sentry with one container you own.
OpenFault is an error tracker your existing SDKs already speak. Change the DSN and you’re done. It idles under 100 MB of RAM, it’s MCP-first so your agents can triage, and it’s open source.
docker run -d -p 8080:8080 -v openfault:/data ghcr.io/openfault/openfault | Issue | 24h | Events | Users | Seen |
|---|---|---|---|---|
| TypeError Cannot read properties of undefined (reading 'id')Regressed app/checkout/[id]/page.tsx in loadOrder | 1,204 | 212 | 2m | |
| ActiveRecord::RecordNotFound Couldn't find Invoice with 'id'=<int>New app/controllers/invoices_controller.rb in show | 86 | 41 | 14m | |
| Net::ReadTimeout Net::ReadTimeout with #<TCPSocket:(closed)> app/jobs/sync_stripe_job.rb in perform | 532 | 3 | 1h | |
| ZeroDivisionError division by zero billing/usage.py in proration | 19 | 7 | 3h | |
| Error Hydration failed because the server rendered HTML didn’t match components/PriceTag.tsx in PriceTag | 3,890 | 1,018 | 5h |
01 · Drop-in
Keep your SDKs. Change one line.
OpenFault speaks the Sentry envelope protocol. The official Sentry SDKs post to it as they are. No fork, no plugin, no wrapper.
- Rails
- Next.js
- Node
- Python
Minified stack traces? sentry-cli sourcemaps upload works against it, same flags, same debug IDs.
Not doing Tracing, session replay, profiling. On purpose. OpenFault tracks errors. That is the whole job.
sentry.client.config.ts
Sentry.init({
- dsn: "https://k3y@o1234.ingest.sentry.io/56",
+ dsn: "https://k3y@errors.example.com/1",
tracesSampleRate: 0,
}); 02 · Grouping
Grouping that doesn’t split bugs.
Issues are keyed on the shape of the stack: module, file, function. Never line numbers. Add a log line above the crash and the next event still lands in the same issue.
A second key on exception type and message catches refactors that move the stack. Want your own rule? Send a fingerprint. {{ default }} keeps our key in the mix.
Two events, one issue
Custom fingerprint
Sentry.captureException(err, {
fingerprint: ["{{ default }}", tenant.region],
}); 03 · MCP
Built for agents. Gated by people.
MCP is built in. Every tool calls the same handler the UI uses, so an agent sees what you see and nothing more.
An agent can list, search and triage. It can’t read the stack or start a fix until a person clicks Approve. Captured data is untrusted: every message, breadcrumb and tag comes back fenced, with a note telling the model not to follow it.
- list_new_issues
- search_issues
- get_issue
- resolve_issue
- mute_issue
- link_fix
Claude Code
claude mcp add -t http openfault https://errors.example.com/mcp -H "Authorization: Bearer $OPENFAULT_TOKEN" get_issue 4812
TypeError in app/checkout/[id] · 212 users
first seen 1.42.0 · last seen 2m ago
Fix not approved. Ask a person to approve it in OpenFault. 04 · One container
One container. One volume. That’s the stack.
A Rust binary and SQLite. No Redis, no Kafka, no Postgres, no ClickHouse. It runs next to your app on the small VPS you already pay for.
- Image
- ~12 MB
- RAM at 4k errors/day
- < 100 MB target
- Default retention
- 90 days
- Backup
- /data Copy the volume. Done.
05 · Teams
Teams, email, iOS.
It’s for the whole team, not just whoever set it up.
- Invites and roles
- Owner, admin, member. Invite by email or send a link. Closed signup by default.
- Alerts
- Email, Slack, Discord, or any webhook. On new issues, regressions and spikes, per person, per project.
- iOS Coming
- A native app with home and lock screen widgets, and push with Resolve and Mute right on the notification. Pair it by scanning a QR code.
06 · Compare
How it stacks up.
OpenFault numbers are design targets until the first release. A dash means we haven’t checked.
| OpenFault | Sentry self-hosted | Bugsink | |
|---|---|---|---|
| Containers to run | 1 | 10+ | 1 |
| RAM | Under 100 MB (target) | 16 GB + 16 GB swap minimum, 32 GB recommended | — |
| Runtime | Rust + SQLite | Python, Kafka, ClickHouse, Postgres, Redis | Python |
| Sentry SDK compatible | Yes | Yes | Yes |
| Source maps | Yes, via sentry-cli | Yes | Yes, via sentry-cli |
| MCP server | Built in, approval-gated | Separate server | — |
| iOS app | Coming, with widgets and push | — | — |
| License | MIT | FSL-1.1-Apache-2.0 | PolyForm Shield 1.0.0 |
07 · Install
Running in a minute.
One command, no config. The secret key is generated into /data on first boot.
-
Start the container.
docker run -d -p 8080:8080 -v openfault:/data ghcr.io/openfault/openfault Open
http://localhost:8080. The setup wizard creates your admin account and first project.Copy the project’s DSN into your Sentry SDK config. Deploy. Watch the first error come in.
08 · FAQ
Questions.
Is it really drop-in?
For errors, yes. OpenFault accepts the same envelope endpoint the Sentry SDKs already post to. Point the DSN at your server and events land. Items we don’t handle, like transactions, are dropped, not rejected, so your app never notices.
What about performance tracing?
Not planned. No tracing, no session replay, no profiling. If you need those, keep a tool for them and send errors here. Doing one job is how this stays one small container.
Can I migrate from Sentry?
Change the DSN in each app and deploy. New errors flow into OpenFault from then on. We don’t import history, so keep Sentry around read-only until you stop needing the old issues.
How is data retained?
Events are kept for 90 days by default, set per project. Within an issue we keep the first 25 events of each hour, then 1 in 20, and the counters always count. A noisy bug can’t fill your disk. Everything lives in /data.
Is it production ready?
Not yet. OpenFault is in active development and nothing here is ready for production. Follow the repo on GitHub to see when the first release ships.