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
errors.example.com/acme/web/issues Preview
is:unresolved env:production Last seenUsersEvents
Issue24hEventsUsersSeen

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://[email protected]/56",
+  dsn: "https://[email protected]/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

evt a1f3order.rb:42Order#total
evt 9c07order.rb:57Order#total
keyorders | order.rb | total#4812

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 MBtarget
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.

OpenFaultSentry self-hostedBugsink
Containers to run110+1
RAMUnder 100 MB (target)16 GB + 16 GB swap minimum, 32 GB recommended—
RuntimeRust + SQLitePython, Kafka, ClickHouse, Postgres, RedisPython
Sentry SDK compatibleYesYesYes
Source mapsYes, via sentry-cliYesYes, via sentry-cli
MCP serverBuilt in, approval-gatedSeparate server—
iOS appComing, with widgets and push——
LicenseMITFSL-1.1-Apache-2.0PolyForm Shield 1.0.0

07 · Install

Running in a minute.

One command, no config. The secret key is generated into /data on first boot.

  1. Start the container.

    docker run -d -p 8080:8080 -v openfault:/data ghcr.io/openfault/openfault
  2. Open http://localhost:8080. The setup wizard creates your admin account and first project.

  3. 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.