# Error relay

The error relay is a Cloudflare Worker that takes Sentry alerts from every OCTYN project and posts them into one Telegram supergroup. Each alert arrives as a short caption with a full-context markdown file attached, so the phone notification is readable and the detail is one tap away. Internal, recorded 2026-07-06.

Domain: Our own · Error relay
Label: Running (our own)
For your engineering team. Inside: error intake · readable summaries · phone alerts with the trace

This relay is OCTYN's own internal plumbing. It is the smallest system on this list, it has no interface, and it is the one whose absence would be noticed the same day.

## The situation

Errors that arrive somewhere nobody is looking are not alerts. They are a log.

Every OCTYN project reports its errors to one error-tracking service, and that service's own delivery is email and a dashboard. Both of those are places a person goes, at a time they choose, which is the wrong shape for the only question an alert has to answer: is something broken right now, while nobody is at the desk. The place that gets looked at within a minute is a phone notification, in the same chat app that already carries everything else here.

## Why it was hard

It is not hard. It is fiddly, and the fiddliness is entirely about length.

A useful error report is a stack trace, a release tag, the request that caused it and the environment it happened in. That is far past what a chat message can carry: the messaging service caps a message length, and a real trace passes that on its own. So the naive version truncates, and a truncated trace is worse than no trace, because it looks like information and is not.

The other half of the problem is the opposite one. If the notification itself is long, the phone shows the first line and the rest is a scroll, and the thing that needed to be known in three seconds is buried in the thing that needed three minutes to read. Those are two different documents, being treated as one.

## What was built

A small relay that sits between the error tracker's webhook and the chat app's messaging API, fanning every project into one shared group.

The message is split by what each half is for. The caption is short and readable on a lock screen: what broke and where. The full context goes out as an attached file, so the detail is one tap away and the notification stays a notification. The chat app renders the attachment inline when it is opened, which is why the attached format is chosen for exactly that.

One shared group for every project, rather than a channel each. The number that matters at a glance is whether anything at all is on fire, and splitting that across twenty channels turns one look into twenty.

Running this as a small, independent relay rather than a service on OCTYN's own machines is deliberate: an alerting path that depends on the same servers it watches goes quiet exactly when those servers are the problem. This runs on infrastructure that is none of the things it watches.

## What it does under load

It covers every project OCTYN runs, recorded internal on 2026-07-06 with no public surface.

What is not measured: there is no timing on the hop itself. The claim on the work page is that an error reaches a phone in seconds. That is a wall-clock observation, not an instrumented figure, and it is published as what it is. Nothing in the relay records how long the tracker took to fire, how long the relay took, or how long delivery took.

Volume has not been a problem, and the reason is structural, not luck: the error tracker groups and rate-limits on its own side, so what arrives here is distinct issues rather than raw events.

## What happens when it breaks

This is the part that matters for a piece of alerting, and the honest answer has a hole in it.

If the relay fails, the alert does not arrive. There is no second channel and no heartbeat, so a relay silently broken for a week looks exactly like a week with no errors. That is the known weakness of this design. It is the sort of thing only discovered during an incident, and a periodic test alert is the obvious fix that has not been built yet.

If the chat app is unavailable, the same thing holds, with the mitigation that the error tracker still has everything. Nothing is lost, only the speed of finding out.

If a payload is malformed or oversized, the split is what saves it: the caption is generated from fields, not from the trace, so a trace that cannot be parsed still produces a readable notification with an attachment that may be ugly.

## Who maintains it, and what that costs in attention

Nobody, most of the time, and that is a real property, not a claim made for effect. It has no database, no queue and no state to drift. The maintenance it does need is triggered from outside: a change in the tracker's webhook payload, or a change in a messaging limit.

Its real attention cost is the one above. A system nobody maintains and nobody tests is a system trusted more than it has earned.

## What changes when requirements change in six months

Configuration, no deploy: which projects report, and where they land.

A small code change: routing by severity, a different destination per project, a quiet window overnight.

A larger code change: anything that needs to remember. Acknowledgement, escalation, and whether an alert has been seen all require state, and this has none by design. Adding it is the moment this stops being a relay.

A rebuild: two-way control. Replying to an alert to restart something is a different security posture entirely, because a chat group that can act on production is a chat group that is now a credential.

## What we would do differently

Send a heartbeat. Everything else here is right, and the absence of a test alert means the one thing this system promises has never been verified after the day it was built.

Time the hop. The claim is speed, and speed is the one claim here with no figure behind it.

## Related

- [The Consult](https://octyn.co/consult)

Canonical: https://octyn.co/casestudies/sentry-telegram-relay
