Rustrak: error tracking on your own hardware with Sentry SDKs
Ultra-lightweight error tracking server compatible with Sentry SDKs
At a glance
- What is it?
- Rustrak is a self-hosted error tracker that accepts the standard Sentry envelope, so an existing SDK only needs a different DSN. It runs as one process on SQLite by default, which makes deployment cheap and leaves protocol parity, telemetry defaults and pre-1.0 versioning as the real decision points.
- Who is it for?
- Adopt Rustrak when you want Sentry protocol compatibility without a per-event SaaS bill and you are willing to own the process, the disk and the upgrades. Skip it if your monitoring setup depends on Sentry specific features outside the envelope contract, or if a pre-1.0 release train moving several versions in three days is a risk your team cannot absorb.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The third option between a SaaS bill and a full Sentry deployment
Rustrak is a self-hosted error tracker that accepts the standard Sentry envelope, so the SDK you already have can point at it by changing one string in the DSN. The problem it addresses is narrow and worth stating plainly: teams that want the Sentry protocol without a per-event SaaS bill, and without provisioning the pieces a self-hosted Sentry stack asks for. The README also puts it well beyond crash reports, taking logs, transactions, release health and AI-agent traces. That wider surface has a practical consequence. A monitoring server that handles only exceptions still leaves you with a second system for logs and traces, and the second system is where the operational cost usually hides. Rustrak's pitch is that one process can answer all of it, and the license, the GPL-3.0, is the price of that choice.
Two-phase ingestion: the endpoint returns 200 before the database work
The ingestion path is the part worth understanding before you deploy it. The endpoint parses the envelope, writes it to disk and returns 200, and a spawned task then does the database work. Accepting an event therefore never waits on the database, and the README credits this with what stops a traffic spike from turning into a timeout inside your own application. The performance numbers attached to that design are specific: on a 4-core box with SQLite, a burst of 20,000 events is accepted at about 5k events per second with the server peaking under 60 MB of memory. There is a consequence in the other direction. Because the database write happens in the spawned task, the client already holds its 200 while the event is still settling, so there is a window where an accepted event is not yet visible in the dashboard. A monitoring UI that looks empty right after a burst is therefore not evidence that the events were lost.
Static dashboard files served by the same process
One small process answers both the API and the UI because the dashboard is static files the server hands out. That single decision shapes the deployment in two ways. An image built without the dashboard is a complete product on its own, which is how the dashboard can sit on a different host from your data through the separate rustrak/rustrak-ui image behind nginx, following the production guide. In the default setup there is also no second port and no address to tell one half about the other: the same container serves the dashboard and the API on 8080. Teams that have run a split monitoring stack with a separate UI service and a separate database host will recognise how much of that operational surface disappears here, and they will also recognise what they give up, since there is no documented path for storing the event data somewhere other than the server's own disk.
One compose file is the whole SQLite install
SQLite is the default, so there is no database to provision and no broker to run. The compose file in the repository looks like this.
services:
server:
image: rustrak/rustrak-server:latest
ports: ["8080:8080"]
volumes: [rustrak_data:/data]
environment:
- SESSION_SECRET_KEY=${SESSION_SECRET_KEY}
- CREATE_SUPERUSER=${CREATE_SUPERUSER}
restart: unless-stopped
volumes:
rustrak_data:The two environment variables are set before the stack starts.
export SESSION_SECRET_KEY=$(openssl rand -hex 32)
export [email protected]:changeme123
docker compose up -dAfter that, opening http://localhost:8080 and signing in with those credentials gets you to the dashboard and the API from one container. Note that the second export hard-codes an example password, so treat that value as something to replace before the stack is reachable by anyone else. The repository's own compose file adds more knobs than the README shows, including PUBLIC_URL, which is needed when the address people and SDKs reach differs from the bind address, and the OIDC variables for single sign-on.
Pointing an existing Sentry SDK at the new DSN
Migrating is a configuration change rather than a project. You create a project in the UI, copy its DSN, and change one line in your application. The Python SDK takes it like this.
# Python
import sentry_sdk
sentry_sdk.init(dsn="http://<key>@localhost:8080/<project_id>")The browser SDK uses the same shape of DSN.
// JavaScript
import * as Sentry from "@sentry/browser";
Sentry.init({ dsn: "http://<key>@localhost:8080/<project_id>" });And Go follows the same pattern.
// Go
sentry.Init(sentry.ClientOptions{Dsn: "http://<key>@localhost:8080/<project_id>"})Any Sentry SDK works, in any language, and the README makes a practical suggestion for the evaluation phase: if you are already sending to Sentry, point a second DSN at Rustrak and compare the two before committing. That parallel run is also the cheapest way to find out which Sentry features your code actually depends on, which matters because the protocol compatibility is the whole premise.
Deterministic issue grouping, and token counts without a spend widget
Errors are grouped into issues by a deterministic fingerprint: the one your SDK sent if it sent one, otherwise the exception type plus the first line of the message plus the transaction. Same input, same group, every time, so an issue does not split in two after a deploy. From the list you can triage in bulk, filter by status, and read each issue's 24-hour trend without opening it, and source map upload resolves a minified frame back to the line you actually wrote. The agent page is a separate surface: runs over time, duration percentiles, top models by calls and by tokens, top tools, and a per-trace waterfall of every LLM call, tool call and handoff in order. Rustrak reads Sentry's Spans Protocol v2, the batched format real SDKs use for AI spans, verified against @sentry/node with the Vercel AI SDK, and it also takes standalone OTel-style spans with no parent transaction. Enabling it needs no server-side setup, only one integration.
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: 'http://<key>@localhost:8080/<project_id>',
integrations: [Sentry.vercelAIIntegration()],
});There is deliberately no spend widget, because per-model pricing goes stale faster than the project can ship it. Rustrak reports exact token counts and leaves the multiplication to you, which is a reasonable trade for a self-hosted tool and means your cost reporting stays in your own hands.
Defaults worth changing before real traffic arrives
The repository's compose file carries three settings that deserve attention. Anonymous telemetry is on by default, and the environment block offers a commented RUSTRAK_TELEMETRY=off line to turn it off. The same block states that /metrics is unauthenticated and should be restricted before RUSTRAK_METRICS is set to on. Both are easy to miss in a file that most people copy once and never read again, and both belong in your deployment checklist. Then there is the protocol ceiling. Rustrak speaks Sentry, so anything that lives outside the Sentry protocol is not part of the contract, and the README's claim that your SDK never learns it is talking to something else is true for events while leaving the question of Sentry specific features open. Retention is documented elsewhere rather than here: v0.18.0 is titled Crons and Retention, but the README does not spell out the retention settings themselves.
Pre-1.0 versioning, a monorepo build and the GPL-3.0 terms
The repository is not archived, and the last push was on 2026-10-20. Three releases landed within two days of that push: v0.19.0 on 2026-10-19, titled Built-in MCP Server, v0.18.1 on 2026-10-18, titled Faster Storage Page, and v0.18.0 on 2026-10-18, titled Crons and Retention. The pace is fast and the version numbers are still below 1.0, so treat the release cadence as a change rate to plan for rather than a stability guarantee. The build is a pnpm workspace driven by turbo, with a Rust server package and TypeScript packages, and the CI scripts run format checks, lint, tests, type checks and an openapi:check against the server, which is where you would look to judge the state of the tree. The licence is the GPL-3.0. Whether distributing a modified Rustrak or embedding it inside a product creates obligations for you is a question for your own legal review, and the README points to the LICENSE file rather than discussing it.
Editorial conclusion
Adopt Rustrak when you want Sentry protocol compatibility without a per-event SaaS bill and you are willing to own the process, the disk and the upgrades. Skip it if your monitoring setup depends on Sentry specific features outside the envelope contract, or if a pre-1.0 release train moving several versions in three days is a risk your team cannot absorb. Before the first real event lands, verify that the compose file has PUBLIC_URL set, that RUSTRAK_TELEMETRY=off is uncommented if you do not want telemetry, and that the superuser password from the quickstart has been replaced.
Frequently asked questions
How do I install Rustrak and run it with SQLite?
Use the docker-compose.yml in the repository, set SESSION_SECRET_KEY with openssl rand -hex 32 and CREATE_SUPERUSER with an email and password, then run docker compose up -d. The server and the dashboard are both served on port 8080, so there is no second service to start.
Can I keep using my existing Sentry SDK with Rustrak?
Yes. Rustrak accepts the standard Sentry envelope, so you create a project, copy its DSN, and change one line in your SDK init call. The README suggests pointing a second DSN at Rustrak while you still send to Sentry, so you can compare the two before committing.
How does Rustrak handle AI agent traces?
With one integration in Sentry.init, agent runs appear on their own page with runs over time, duration percentiles, top models by calls and tokens, top tools, and a waterfall of every LLM call, tool call and handoff. Rustrak reads Sentry's Spans Protocol v2 and also accepts standalone OTel-style spans with no parent transaction.
How often is Rustrak released, and is the repository still worked on?
The last push was on 2026-10-20, and releases v0.19.0, v0.18.1 and v0.18.0 all landed between 2026-10-18 and 2026-10-19. The versions are still below 1.0, and the project uses changesets for its release notes.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rustrak-rustrak)Was this useful?