Broker-agnostic · Self-hosted
One secure control plane for
dead-letter queue recovery
One tool for every broker — not a different console for each. Inspect, diagnose, transform, and replay failed messages across SQS, RabbitMQ, ActiveMQ / Amazon MQ, Azure Service Bus, Google Pub/Sub, and Anypoint MQ — all self-hosted, so message data never leaves your network.
Single Go binary · React UI embedded · No sidecars or reverse proxy · Postgres + Redis →Purpose-built for dead-letter recovery
Replace ad hoc scripts with a secure, auditable DLQ operations workspace.
Inspect messages
Peek at dead-letter payloads, headers, attributes, and receive history without consuming or losing messages.
Payload editing & replay
Fix malformed messages in place, then replay individually or in bulk with a complete audit trail.
JavaScript transforms
Author reusable transforms to clean, reroute, or reject messages before they re-enter your system.
Automated replay rules
Schedule rules to match DLQs, filter messages, and replay them automatically with optional transforms.
AI-assisted diagnosis
Use your own API key for a supported LLM provider — Anthropic, OpenAI, or any compatible model — to get a structured cause analysis and remediation suggestions for failed messages.
Immutable audit trail
Every edit, replay, and rule action is logged with actor, timestamp, original payload, and modified payload.
S3, GCS & Azure Blob storage remediation
Browse, fix, and replay poison objects in S3-compatible, Google Cloud Storage, or Azure Blob buckets with the same inspection, transform, and audit tooling used for queues — without handing out bucket credentials.
Observability & tracing
Replay events become correlated OTEL spans in Datadog, Grafana, or any OTLP backend — with W3C traceparent propagation so the chain stays unbroken. A native trace timeline works independently, with no OTEL infrastructure required.
Prometheus metrics endpoint
A built-in /metrics endpoint exposes per-queue DLQ depth, replay counts, firing alert rules, and federation peer health — ready to scrape with any Prometheus-compatible monitoring stack for SRE dashboards and on-call rules.
Architecture export (ArchiMate)
Generate a live ArchiMate 3.1 or 3.2 Open Exchange model of the running instance and its federation peers — host, OS, runtime, queue and storage endpoints, and the mTLS federation mesh. Poll the REST endpoint on a cadence to feed Archi, BiZZdesign Blue Dolphin, or any modeling tool, or explore it in-app as a filterable list and layered topology diagram.
MCP server for AI agents
A built-in Model Context Protocol endpoint lets any MCP client query live DLQ state during an incident — queues and depths, redrive policy, depth history, alert state, replay history, archived objects in your storage buckets, and full message traces across every broker Triage supports. Strictly read-only by design: no replay, no purge, no peeking at messages still sitting in a queue, and every tool runs with the caller's own role.
Payload-at-rest encryption
The before/after body snapshots Triage stores can be sealed with application-layer AES-256-GCM envelope encryption, keyed by a raw master key or a cloud KMS (AWS, GCP, or Azure) — so a database breach yields only ciphertext. Or configure Triage to never persist payloads at all, or to scrub them after a fixed retention window. Every option keeps the full metadata audit trail.
Why Triage, and not the tools you already have
Almost every alternative is locked to a single ecosystem — Turbo360 to Azure, QueueForge to RabbitMQ — or is a single-machine desktop explorer with broker credentials sitting on a laptop. Triage is the one that spans every broker and runs entirely inside your own infrastructure. It's the only column below that holds all of these at once.
| Capability | Cloud console SQS redrive · Azure portal | Desktop explorer QueueExplorer · viewbus | Single-vendor SaaS Turbo360 · QueueForge | Triage |
|---|---|---|---|---|
| Every broker in one console SQS, RabbitMQ, Service Bus, Pub/Sub, Anypoint MQ | ✕ | ~ | ✕ | ✓ |
| Runs in your own infrastructure Message data never leaves your network | ✓ | ✕ | ✕ | ✓ |
| Programmatic JavaScript transforms Reusable and testable — not just edit-a-body | ✕ | ✕ | ~ | ✓ |
| Automated, scheduled replay rules | ✕ | ✕ | ✓ | ✓ |
| Immutable audit trail + role-based access Who read, edited, or replayed each message | ~ | ✕ | ✓ | ✓ |
| Payload encryption against a live DB breach AES-256-GCM envelope encryption, KMS-wrapped key | ✕ | ✕ | ✕ | ✓ |
| DLQ replays as OTEL spans + trace timeline Failed messages stay on the trace graph | ✕ | ✕ | ✕ | ✓ |
| S3 / GCS / Azure Blob poison-object remediation Same workflow for rejected files as messages | ✕ | ✕ | ✕ | ✓ |
| Read-only MCP server for AI agents Point an AI agent at your DLQs during an incident | ✕ | ✕ | ✕ | ✓ |
Remove direct broker and bucket access — without removing capability
Instead of giving developers direct access to your message brokers — or credentials to your S3, Google Cloud Storage, or Azure Blob buckets — Triage becomes the secure control plane. Broker and storage credentials stay server-side. Your team authenticates with their own identity and gets role-based capabilities.
Without Triage
- ✕ Developers hold direct broker access — credentials shared via Slack or wikis
- ✕ S3/GCS/Azure Blob bucket credentials handed out to anyone who needs to inspect rejected files
- ✕ No audit trail — no record of who read which message or triggered a replay
- ✕ Support staff get over-privileged access to handle incidents
- ✕ The engineer who writes the fix-up script needs an admin account to save it
- ✕ Leavers retain access until credentials are manually rotated
- ✕ Payload edits happen ad-hoc in scripts with no record of changes
With Triage
- ✓ Broker and storage (S3/GCS/Azure Blob) credentials are server-side environment variables — humans never handle them
- ✓ Every replay logged with actor, timestamp, queue, and transform applied
- ✓ Support staff get the Viewer role — read messages, no replay capability
- ✓ Transform authors get the Developer role — write and version scripts, without replay, configuration, or message payloads
- ✓ Revoking a user's Triage account removes all access instantly
- ✓ Payload changes only happen through named, attributed transforms
Role-based access tiers
Viewer, Operator, and Admin nest. Developer deliberately doesn’t — it grants authorship of transform scripts and nothing else, so the person who writes the fix never has to be handed replay, purge, user management, or the message payloads themselves.
Viewer
Browse queues, read messages, search. No replay or changes.
Operator
Replay, apply transforms, manage rules. Cannot configure system.
Developer
Write, test, and version transform scripts — and nothing else. No replay, no config, no message payloads.
Admin
Full access — users, providers, transforms, rules, sinks.
Service Account
Scoped API tokens for automated integrations.
Protect stored payloads — even from a database breach
The only sensitive payload Triage keeps is the before/after body snapshot on every replay and storage remediation — the data that powers the diff, the message trace, and the audit log. At-rest volume and RDS encryption protect a stolen disk or backup, but they do not protect against a live database breach: Postgres decrypts transparently for anyone who can connect. These three opt-in controls govern how — or whether — that payload is persisted, and all three preserve the full metadata audit trail.
Envelope encryption Encrypt bodies against a live-DB breach
Stored payloads are written as AES-256-GCM ciphertext. The data key lives only in application memory, wrapped at rest by a raw master key or a cloud KMS — AWS KMS, GCP KMS, or Azure Key Vault. Ciphertext read out of the database is useless without the key, which a database-level attacker never holds. Diffs still work: bodies decrypt at render time.
SNAPSHOT_CAPTURE=false Don’t persist payloads at all
Audit rows are written without bodies — the payload is dropped at insert time and never touches the database. You keep the full "who remediated what, when, on which queue" record; you give up the before/after diff. This is the "we can be configured to never store payloads" answer.
SNAPSHOT_RETENTION_DAYS=N Scrub payloads after N days
An hourly, leader-gated job blanks body columns older than N days while keeping the metadata row intact — capping the blast radius of a breach to the last N days of payloads without losing the compliance trail. Scoped to the provider names each instance owns, so it never touches a co-tenant’s bodies in a shared database.
| Control | Before/after diff survives? | Defends a live-DB breach? | Notes |
|---|---|---|---|
| At-rest / RDS / volume encryption | Full | No | Protects stolen disks and backups only — Postgres decrypts transparently for anyone who can connect. |
| SNAPSHOT_RETENTION_DAYS | Until expiry | Partial | Caps exposure to the last N days of payloads. |
| SNAPSHOT_CAPTURE=false | None | Yes | Bodies never stored; metadata audit trail preserved. |
| Application-layer envelope encryption | Full | Yes | The only option that keeps diffs and defends a breach. DEK wrapped by a raw master key or a cloud KMS. |
Envelope encryption is the only control that keeps the diff and defends a live-DB breach. The data key is unwrapped once at startup and pinned in memory, so per-message encrypt/decrypt is pure local AES-256-GCM with no KMS call on the hot path. Cloud KMS key providers require the kms license feature; the raw master-key provider is always available. Redaction and masking are deliberately not offered — they degrade the diff while giving a weaker guarantee than encryption.
Close the observability gap on DLQ operations
Most OTEL-instrumented systems have a blind spot: failed messages that land in dead letter queues vanish from the trace graph. Your services emit spans — but the moment a message is dead-lettered, the story ends. Triage closes that gap, making every DLQ replay a correlated, traceable event inside your existing observability platform.
Native trace timeline
Every replayed message is stamped with a root_triage_message_id that persists across every subsequent hop — queues, storage, transforms, federation peers. A single click from the Replay Log opens the full chronological journey of that message, with no OTEL infrastructure required.
OTEL span export
Set OTEL_EXPORTER_OTLP_ENDPOINT and every replay span — including storage actions — is exported via BatchSpanProcessor to your existing collector. Replay events surface in Datadog, Grafana Cloud, Honeycomb, Jaeger, or any OTLP-compatible backend alongside your service traces, with no new tooling or dashboards needed.
W3C traceparent propagation
Triage injects the W3C traceparent header into outgoing replay message attributes, and extracts it from inbound DLQ messages. Downstream services see the Triage replay as a continuation span inside the original distributed trace — not a new orphan event. The chain stays unbroken.
Alert events in your APM
The OpenTelemetry alert sink emits DLQ depth events directly to your collector — meaning queue depth spikes appear in the same observability platform as your service error rates and latency dashboards. No separate alerting tool required; depth alerts become part of your existing on-call correlation workflow.
Prometheus /metrics endpoint
Triage exposes a built-in GET /metrics endpoint in the Prometheus text format — no plugins or sidecars required. Point any Prometheus-compatible scraper at it (Prometheus, VictoriaMetrics, Grafana Agent, Datadog Agent) and DLQ health becomes part of your existing SRE dashboards and on-call rules.
triage_queue_depth{queue} Current DLQ message count per queue — the primary signal for capacity and backlog alerts.
triage_replays_total Running total of replay events — useful for SLO tracking and anomaly detection.
triage_alert_firing{rule_id, queue, label} 1 if the alert rule is currently firing, 0 otherwise — one time series per rule.
triage_federation_peer_up{peer} 1 if the federation peer's ingest endpoint is reachable — federation mesh health at a glance.
triage_federation_peer_latency_seconds{peer} Round-trip latency of the last federation ping per peer.
triage_federation_peer_cert_expiry_seconds{peer} Unix timestamp when the peer's TLS certificate expires — alert before it causes an outage.
Built for teams already on an OTEL roadmap
Many larger organisations are in the process of standardising on OpenTelemetry Collectors as the single egress point for all telemetry — traces, metrics, and logs — with fan-out to whichever backends they choose. Triage slots into that infrastructure with a single environment variable. The replay events, storage actions, and depth alerts that were previously invisible to your observability stack become traceable, searchable, and correlated with the rest of your services — with no architectural changes required.
Core capabilities
A complete platform for DLQ operations — from discovery to diagnosis to automated recovery.
Dashboard & Visibility
Real-time metrics across all providers — DLQ counts, replay history, active alerts, and federation peer health at a glance.
- → Live DLQ depth and message counts
- → 7–90 day replay history charts
- → Active alert rule count
- → Federation peer latency monitoring
Queue Browser & Search
Unified interface to all DLQs across providers — wildcard search, non-empty filters, and provider tags for instant orientation.
- → Wildcard queue name search
- → Non-empty filter to focus on active issues
- → Provider badges on every row
- → Depth history charts per queue
Message Inspection & AI
Syntax-highlighted payloads, full attributes, optional LLM-powered root cause analysis, and per-message or bulk replay.
- → JSON syntax highlighting and formatting
- → Message attributes (contentType, headers)
- → Optional AI diagnosis with your choice of LLM provider
- → Bulk replay with transforms
Transforms & Routing
Named JavaScript functions to fix payloads, reshape messages, or dynamically re-route — with live test panel and reusable library.
- → JavaScript sandbox — shape, filter, enrich
- → Live test panel with sample payloads
- → Reusable transform library
- → Dynamic destination re-routing
Alerts & Automation
Alert rules watch queue depth and fire when thresholds are exceeded. Replay rules automatically drain queues on a schedule.
- → Depth-based alert rules with sustained thresholds
- → Webhook, SNS, OpenTelemetry, Microsoft Teams, and Opsgenie sinks
- → Cron-based replay rules
- → Transform integration in rules
Audit & Compliance
Immutable replay log with actor, message ID, queue, transform, and timestamp. Exportable to CSV for compliance reviews.
- → Tamper-evident replay audit trail
- → Filter by queue, actor, date range
- → "Modified only" filter for payload changes
- → CSV export for compliance teams
Payload-at-Rest Security
Control how — or whether — Triage stores message and object payloads. Application-layer encryption defends stored bodies against a live database breach, not just a stolen disk; every option preserves the metadata audit trail.
- → AES-256-GCM envelope encryption of stored bodies
- → Data key wrapped by raw master key or cloud KMS (AWS / GCP / Azure)
- → SNAPSHOT_CAPTURE=false — never persist payloads
- → SNAPSHOT_RETENTION_DAYS — scrub bodies after N days
- → Opt-in one-shot backfill to encrypt pre-existing rows
S3, GCS & Azure Blob Storage Remediation
Treat poison objects in S3-compatible, Google Cloud Storage, or Azure Blob buckets like dead-letter messages — browse, fix, diagnose, and replay them back into a queue, with no one needing direct bucket credentials.
- → Prefix, wildcard search, and extension filters
- → Edit, diff, and preview object bodies
- → Replay to queue with optional transform
- → Storage-aware alert rules and full audit log
Observability & Message Tracing
DLQ replays emit OTEL spans to your existing collector and carry W3C traceparent so downstream services see a continuous trace. A native trace timeline works with no OTEL infrastructure at all.
- → OTLP span export — appears in Datadog, Grafana, Honeycomb, Jaeger
- → W3C traceparent propagation keeps distributed traces unbroken
- → Native root_triage_message_id trace timeline (no OTEL required)
- → Alert depth events also emitted to your OTEL collector
- → Built-in /metrics Prometheus endpoint — queue depth, alert state, federation peer health
MCP Server — AI Agent Access
A Model Context Protocol endpoint at /api/v1/mcp lets an SRE point any MCP client at an instance and ask why a queue is filling up, across every broker Triage supports. Read-only by construction: no replay, purge, delete, live message peek, or message bodies of any kind, and every tool runs with the caller's own token and role — a viewer sees ten tools, while an operator or admin token adds the two live cross-peer tools and, where object storage is configured, four storage tools that reach the archived messages a queue no longer holds.
- → list_queues — depth, DLQ status, and capabilities per queue
- → get_queue_config — redrive policy, retention, TTLs
- → get_provider_info — which broker, and what it supports
- → get_instance_info — this instance and its federation peers, at a glance
- → get_stats — replay counts, success rate, live depth totals
- → get_depth_history — filling for days, or spiked ten minutes ago
- → get_alert_status — what Triage already considers wrong
- → list_alert_events — when each rule started and stopped firing
- → list_replays — already retried, by whom, and did it work
- → get_trace — one message's full journey, across federated instances
- → list_federation_peers — which instance a backlog is actually on
- → get_peer_queues — a cross-instance replay target, confirmed over mTLS
- → list_storage_buckets — which archive buckets exist, and are reachable
- → list_storage_objects — archived messages by prefix, key, or extension
- → get_storage_object_metadata — an object's trace lineage, back to get_trace
- → list_storage_events — already republished, moved, or deleted, and by whom
Architecture Model & ArchiMate Export
A dedicated Architecture view renders the live technology and application landscape of the instance and its federation peers, and exports it as a standards-based ArchiMate model that drops straight into enterprise architecture tools.
- → GET /api/v1/export/archimate — ArchiMate 3.1 or 3.2 Open Exchange XML
- → Live model: host, OS, Go runtime, Postgres/Redis, queue and storage endpoints
- → Federation peers modeled at full parity — mTLS mesh and shared-store blast radius
- → In-app list + layered topology diagram with search and node detail
- → Poll on a cadence for Archi / Blue Dolphin, or share a read-only link with architects and SREs
Supports the platforms you already run
Native support for major brokers, plus federation for mixed estates.
Optional: connect a Google Cloud Storage container, an Azure Blob container, or any S3-compatible store — AWS S3, Cloudflare R2, Wasabi, Backblaze B2, DigitalOcean Spaces, or self-hosted MinIO — as a storage backend for poison-object remediation alongside your queues. Credentials stay server-side, just like your brokers.
How teams use Triage
Real situations where Triage replaces ad hoc scripts, shared credentials, and manual heroics.
Service goes down at 2am — 800 messages pile up
A downstream payment processor goes offline for two hours. When it recovers, an operator bulk-replays the entire DLQ in one action. Every replay is logged — actor, timestamp, queue — with no broker credentials ever leaving the server.
Friday deploy breaks message format compatibility
A schema change causes 34 messages to fail immediately. An engineer writes a JavaScript transform to migrate the old format, tests it against a sample payload in the live editor, then applies it across all affected messages in a single replay action.
Support needs to see a message — but not touch it
A customer reports a failed order. A support engineer inspects the full payload and attributes to diagnose the issue — without any replay capability and without anyone handing over broker credentials. The Viewer role gives them exactly what they need and nothing more.
Transient 503s every morning — nobody should wake up for this
A third-party API returns 503s during peak load on a predictable schedule. A replay rule drains the affected DLQ every 15 minutes automatically, applying a transform that adjusts retry headers before re-injection.
Unknown failure from a new integration partner
Messages from a new partner start failing with a cryptic error. An operator clicks Diagnose with AI — the configured LLM analyses the payload structure and attributes and identifies a mismatched content-type header as the root cause in seconds.
Security team requests a Q3 access audit
The security team needs evidence that no production message data was accessed without authorisation. The replay log is filtered by date range and exported to CSV — showing every actor, action, queue, and timestamp ready for the review.
A batch job dumps unprocessable files into a storage bucket
A nightly import job moves files it can't parse into a "rejected" prefix in an S3, GCS, or Azure Blob bucket. Rather than issuing IAM credentials so an engineer can poke around the bucket, an operator browses it in Triage, edits a malformed CSV in place, and replays it straight to the processing queue — with the move recorded in the storage audit log.
A message crosses three environments — where did it go?
A payment event enters SQS in production, gets replayed via a Triage rule to a staging Anypoint MQ queue for re-processing, and ends up in a storage bucket after a second failure. A single trace link on the original replay event shows the complete journey — all hops, timestamps, and destinations — assembled in real time from each federated Triage instance.
"Why is orders-dlq filling up?" — asked to an agent, not a colleague
On-call points their AI agent at the Triage MCP endpoint with their own viewer token and asks the question directly. The agent walks the incident itself: which alert rules are firing and when they started, whether depth has been climbing for days or spiked ten minutes ago, what the redrive policy says about why messages are landing there, and whether these messages have already failed replay three times. With federation configured it does this across the whole mesh from that one endpoint — comparing peer workloads to find which instance the backlog is actually on. It comes back with the picture — and cannot replay, purge, or so much as peek at a message still sitting in the queue to get it.
On-call needs the blast radius before touching anything
A replay backlog spikes at 3am and the responder has never seen this deployment. They open the Architecture view: the layered diagram shows which queue provider and storage backend this instance talks to, which Postgres and Redis it shares with federation peers, and where the shared-failure domains are. A read-only share link goes straight into the incident channel so architects and engineers see the same live picture — no one waiting on a stale Visio.
Want to see every feature in detail?
View the full interactive presentation with screenshots, feature breakdowns, security architecture, and provider-specific technical details.
Open presentation →Frequently asked questions
Common questions from teams evaluating Triage.
What does Triage need to run?
Triage is self-hosted and ships as a Docker image or Node.js application. It requires PostgreSQL (for audit log and configuration storage) and Redis (for session management and job queuing). It runs on any Linux server with 1 vCPU and 1 GB RAM or above — more for high replay volume. Users access it from any modern browser — Chrome, Firefox, Safari, or Edge. No agent or client software is installed on user machines.
Does Triage send my message data outside my network?
No. Message payloads, attributes, and credentials never leave your infrastructure. Triage connects directly to your brokers server-side. The only optional external call is to your configured LLM provider (Anthropic, OpenAI, or any compatible model) for AI diagnosis — and that is opt-in, requires your own API key, and only sends the specific payload you choose to diagnose.
Can an attacker who breaches the database read our message payloads?
Not if application-layer encryption is enabled. The only sensitive payload Triage stores at rest is the before/after body snapshot on each replay and storage remediation. With envelope encryption on, those bodies are written as AES-256-GCM ciphertext whose data key lives only in application memory — wrapped at rest by a raw master key or a cloud KMS (AWS KMS, GCP KMS, or Azure Key Vault). Ciphertext read out of the database is useless without the key, which a database-level attacker never holds. This is the distinction that matters: at-rest volume/RDS encryption protects a stolen disk or backup but gives nothing against a live DB breach, because Postgres decrypts transparently for anyone who can connect. Encryption keeps the before/after diff fully working — bodies decrypt at render time. The data key is unwrapped once at startup and pinned in memory, so there is no KMS call on the per-message path. Cloud KMS providers require the "kms" license feature; the raw master-key provider is always available.
Can we run Triage without it ever storing our message payloads? How long are payloads retained?
Both are your choice. Set SNAPSHOT_CAPTURE=false and audit rows are written without bodies — the payload is dropped at insert time and never touches the database; you keep the full "who remediated what, when, on which queue" record and give up only the before/after diff. Alternatively, set SNAPSHOT_RETENTION_DAYS=N and an hourly, leader-gated job scrubs body columns older than N days while keeping the metadata row intact, capping the blast radius of a breach to the last N days. By default bodies are retained indefinitely. Retention scrubbing is scoped to the provider names each instance owns, so in a shared database one instance’s policy never scrubs a co-tenant’s bodies. These controls compose with encryption — you can encrypt bodies and time-box them.
Is an LLM API key required?
No. AI-assisted diagnosis is an optional feature. All core capabilities — inspection, transforms, replay, audit trail, and automation rules — work without it. If you enable it, Triage uses your own API key for your chosen LLM provider so usage is billed directly to your account and remains under your control.
How does authentication work?
Triage supports local credentials out of the box and integrates with OIDC/SSO providers for teams that require it. Role assignment (Viewer, Operator, Developer, Admin, Service Account) is managed in the Triage admin console, and can be derived from an OIDC group claim so your IdP stays authoritative. Service accounts authenticate via scoped API tokens for automated integrations.
Can an engineer write transforms without being made an admin?
Yes — that is the Developer role. Writing a transform script is a developer's job; operating the queue it runs on is not, so Developer grants authorship of transforms (create, test, clone, version, edit) and nothing else. It is not a rung on the Viewer → Operator → Admin ladder: a developer cannot replay, purge, manage users, issue tokens, or edit replay rules, and it is explicitly not trusted with production message payloads — the reads that return a body (queue peeks, the replay log, and message traces) are closed to it, so scripts are tested against sample payloads pasted into the editor. Two further guards apply. A developer cannot edit a transform an enabled replay rule already references, because that would silently change what production replays do on the rule's next tick — the editor points them at clone-and-edit, and an admin owns the promotion. And delete, which takes the version history with it, is limited to the transform that developer last authored; anyone else's is an admin decision.
Can Triage work with files stored in S3, Google Cloud Storage, or Azure Blob, not just queues?
Yes. Triage can connect to a Google Cloud Storage bucket, an Azure Blob container, or any S3-compatible store as a storage provider for poison-object remediation — files that a pipeline couldn't process and moved aside. The S3 provider is not limited to AWS: point it at an endpoint and it works with AWS S3, Cloudflare R2, Wasabi, Backblaze B2, DigitalOcean Spaces, or self-hosted MinIO, and Triage labels the store by vendor throughout the UI. You get the same browsing, search, edit, diagnose, and replay-to-queue workflow as DLQ messages, plus a dedicated storage audit log and storage-aware alert and replay rules. Bucket credentials live server-side only — no one needs direct bucket access or IAM keys on their laptop to inspect or fix rejected files. This is optional and configured independently of your queue providers.
Does Triage support Apache Kafka?
Not by design — and that's a deliberate choice, not a limitation. Kafka has no dead-letter queue at the broker level: a "DLQ" there is only an application or framework convention (a Kafka Connect dead-letter topic or a Spring DLT), and its failure model is based on consumer offsets and retention rather than per-message removal — a model already served well by dedicated Kafka tooling, and one we're happy not to compete with. Triage is built for brokers with real dead-letter-queue semantics — SQS, RabbitMQ, ActiveMQ / Amazon MQ, Azure Service Bus, Google Pub/Sub, and Anypoint MQ — where failed messages land in a discoverable DLQ you can browse non-destructively, fix, and then replay or clear one message at a time. In practice this is a complement, not a gap: most enterprises run Kafka alongside the classic brokers — RabbitMQ, ActiveMQ, SQS and the rest are almost always in the estate too — and that conventional-queue layer is exactly where Triage lives. It sits happily next to your Kafka tooling and takes the DLQ triage off your plate for everything else, as a single self-contained binary alongside the Postgres and Redis you already run.
Does Triage support message tracing?
Yes. Triage has its own native message tracing — every replayed message is stamped with a triage_message_id and root_triage_message_id. These correlation IDs are written to replay events and storage events, and a trace timeline page reconstructs the full journey of a message across providers, storage actions, and federated Triage instances in chronological order. In addition, Triage emits OpenTelemetry spans for replay paths using a BatchSpanProcessor, and injects the W3C traceparent header into outgoing message attributes so upstream OTEL traces continue through Triage. Configure OTEL_EXPORTER_OTLP_ENDPOINT to ship spans to Datadog, Grafana, Honeycomb, or any OTLP-compatible backend.
Does Triage expose Prometheus metrics for SRE monitoring?
Yes. Triage has a built-in GET /metrics endpoint in the Prometheus text format. It publishes triage_queue_depth (per-queue gauge), triage_replays_total, and triage_alert_firing (per alert rule, labelled by rule ID, queue, and label). When federation is enabled, it additionally exposes triage_federation_peer_up, triage_federation_peer_latency_seconds, and triage_federation_peer_cert_expiry_seconds per peer. Standard Go runtime metrics are also included. Point any Prometheus-compatible scraper — Prometheus, VictoriaMetrics, Grafana Agent, or the Datadog Agent — at <triage-host>/metrics to bring DLQ depth and alert state into your existing SRE dashboards, recording rules, and on-call alerts.
Can an AI agent connect to Triage? What is the MCP server?
Yes. Triage ships a built-in Model Context Protocol server at /api/v1/mcp, so any MCP client can inspect live dead-letter state during incident response. Sixteen tools are exposed, role-scoped: a viewer token sees ten, while an operator or admin token adds the two live cross-peer tools and the four storage tools, the latter only where object storage is configured and licensed.
- → list_queues — every queue with its current depth, DLQ status, and per-queue capabilities.
- → get_queue_config — redrive policy, retention, visibility timeout, and TTLs: why messages are landing here.
- → get_provider_info — which broker this instance is attached to, and which operations it supports.
- → get_instance_info — this instance's id, version, broker and features, plus its federation peers and their health.
- → get_stats — replay counts and success rate over a rolling window, live depth totals, transform and alert-rule counts.
- → get_depth_history — time-series depth for one queue: filling for days, or spiked ten minutes ago.
- → get_alert_status — every alert rule's current state: alerting, ok, or never evaluated.
- → list_alert_events — when each rule started and stopped firing, to line up against a deploy window.
- → list_replays — whether these messages have already been retried, by whom or by which rule, and whether it worked.
- → get_trace — one message's full journey by id: every hop, replay attempt, and transform, including federated instances.
- → list_federation_peers — live workload on every instance in the group: DLQ counts, total depth, and firing alerts, so an agent can find which instance a backlog is actually on.
- → get_peer_queues — the queues on one federated peer that can receive a replay, confirmed live over mTLS before a cross-instance replay is proposed.
- → list_storage_buckets — the buckets this instance archives failed messages to, with backend type, endpoint, and whether each is actually reachable.
- → list_storage_objects — archived objects by prefix, key search, or extension: where to look when a queue is empty but messages are unaccounted for.
- → get_storage_object_metadata — an object's size, content type, and archived x-triage-* lineage, which hands a root id straight to get_trace.
- → list_storage_events — edits, republishes, moves, deletes, and restores against archived objects: has anyone already tried this, and what happened?
Together they cover an incident walkthrough without a human relaying state, and — with federation configured — reach across the whole mesh from the single endpoint the agent is pointed at. The storage tools close the loop the other way: an object found in a bucket carries the lineage to identify the message that produced it, so a queue that reads empty is not the end of the trail. Because Triage is broker-agnostic, an agent gets one consistent tool surface across SQS, RabbitMQ, ActiveMQ / Amazon MQ, Azure Service Bus, Google Pub/Sub, and Anypoint MQ — a question a single-broker cloud console cannot answer. The transport is stateless streamable HTTP, so replicas stay interchangeable behind a load balancer with no sticky routing.
Can an AI agent connected over MCP change anything in production?
No — the tool surface is read-only by design, not by configuration. Replay, purge, and delete are simply absent: remediation stays human-authored, so an agent that can only observe cannot turn a bad inference into a production change. There is also no tool to peek at messages still sitting in a queue, because peeking is a real receive on most brokers and an agent looping it would redrive healthy messages into the DLQ. Nor does any tool return a message body — not the messages queued in a DLQ, and not the before/after snapshots of ones already replayed. The surface is metadata only, by deliberate design: an agent cannot exfiltrate payload contents even for a message a human could open in the Triage UI. list_replays still reports whether a body was modified before it was sent, without exposing either version. The storage tools hold the same line: an archived object's body is never transferred, and neither the sender's own message attributes nor the object's user-defined metadata are returned — only the x-triage-* lineage Triage itself wrote. Object keys are the one thing that cannot be pruned, since they address every storage tool, so MCP_STORAGE_TOOLS=false withholds that group outright for estates whose keys carry customer identifiers. Access is authenticated exactly like the REST API: the endpoint sits behind the same auth middleware and every tool runs with the caller's own token and role, so a viewer token yields a strictly read-only agent and share links are rejected outright. Each tool dispatches into the same handler as the REST endpoint it mirrors, so RBAC, audit logging, error mapping, and provider-capability fallbacks are identical by construction — a tool cannot drift from the endpoint behind it.
Can Triage export its architecture into our EA tooling?
Yes. Triage has a dedicated Architecture view and an admin-only REST endpoint, GET /api/v1/export/archimate, that generates a live ArchiMate Open Exchange model of the running instance and — when federation is configured — its peers. Pass ?version=3.1 or ?version=3.2 (default 3.2) to match your tool. The model is built from real runtime data: host interfaces and OS, Go runtime, Postgres/Redis addresses, the queue provider and storage backend endpoints, and the mTLS federation mesh with shared-store blast radius. Because it is standard ArchiMate 3.x XML, you can poll it on a schedule and ingest it into Archi, BiZZdesign Blue Dolphin, or any compatible modeling tool to keep an always-current view. In-app the same model renders as a searchable list and a layered topology diagram, and you can generate a time-limited read-only share link so architects, support, and engineers — and on-call SREs during break-fix — can see the current-state picture without a Triage login.
Is there a cloud-hosted version?
Not yet — Triage is currently self-hosted only. A managed cloud offering is on the roadmap. In the meantime, the Docker deployment is designed to be straightforward, and we offer implementation services to get you running quickly.
How is licensing priced?
Licensing is priced on the number of message providers you connect, not per seat and not per message — a metric that reflects the size of your estate rather than how badly it is failing. There is a free Community tier for a single provider; Team and Business are annual licences you can buy directly; Enterprise is priced per estate. A licence covers your whole organisation, including unlimited instances and non-production deployments. See the pricing page for the current tiers, or get in touch and we can discuss what fits your environment.
Implementation services
Get up and running faster with hands-on help from the team that built Triage.
Provider setup
We configure your SQS, RabbitMQ, ActiveMQ / Amazon MQ, Azure Service Bus, Google Pub/Sub, or Anypoint MQ connections, validate permissions, and make sure Triage sees the queues it needs.
Transform & routing rules
We build and test JavaScript transforms, replay rules, and cross-provider routing for your message schema and operational workflows.
Team onboarding
A hands-on session with your team covering how to inspect failed messages, replay safely, and use audit-friendly best practices.
Custom integrations
Need Triage to fit into a custom tooling ecosystem or incident workflow? We can extend it with automation and alerts.