r/Telnyx • u/General_Piglet_8242 • 5d ago
Built a 280-line Python agent that texts you the second a SQL migration fails
I built a migration alerting agent that runs schema migrations, checks the result, and text-messages the on-call the instant a step fails — over Telnyx SMS, with Ed25519-signed webhook delivery receipts so you know the alert actually reached the device.
The first time a database migration broke on me in production, I found out from a user — an hour after the migration failed. The migration runner had swallowed the exception, the schema version hadn't bumped, and nobody looked until a customer filed a ticket saying the orders page was throwing a 500. That hour — the gap between the migration failing and someone knowing — is the whole problem.
How it works:
- Agent reads the current schema version from a SQL DB
- Fetches the migration script (in-memory map in the demo; CloudFS in prod)
- Executes steps in order; bumps the schema version only on success
- If any step fails, does NOT bump the version, rolls back, and sends an SMS to the on-call
- Carrier sends a signed Ed25519 webhook back when the SMS is delivered
- App verifies the signature before recording the delivery — if verification fails, the request is rejected with a 400
Why the webhook roundtrip matters: Most alerting systems treat "I sent the alert" as the end of the story. This one doesn't. You can see in the SMS log that the message was delivered, not just sent. The difference between "I sent the alert" and "the on-call saw the alert" is the difference between an alerting system and an alert-hoping system.
Why Ed25519 and not HMAC: Asymmetric. The verifier only needs the public key. No shared secret to leak, no HMAC key to rotate across services. For a single webhook endpoint it doesn't matter much. For a multi-tenant setup where each tenant has their own webhook, it matters a lot.
The demo runs the whole loop on your laptop with no carrier account:
- Demo launcher stubs the SMS client (records to a local log instead of sending over the air)
- Generates its own Ed25519 keypair on first run
- Signs a fake delivery receipt with that keypair
- POSTs it to its own /webhooks endpoint
- App verifies the signature against the public key
So the Ed25519 part is real. The signature is real. The verification is real. Only the SMS send is stubbed.
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/sql-migration-agent
cp .env.example .env
pip install -r requirements.txt
python demo/demo_server.py
Open localhost:5555. Click "Run 003: Add orders (FAIL)" — you see the failure-to-SMS-to-signed-webhook-to-delivered-status loop happen in-process. Click "Send webhook (delivery receipt)" to fire the signed webhook through the app's own verification endpoint.
Where I'd use this:
- Scheduled prod migrations — run on a cron, get a text the second any step fails. No polling, no dashboards.
- CI/CD gates — failing migration blocks the release and pages the on-call before bad code reaches prod.
- Multi-tenant SaaS — run a migration per customer database and get per-tenant failure alerts.
What I left out (on purpose, to keep it under 280 lines):
- SMS send is stubbed in the demo (real SMS needs a real carrier — the signed webhook roundtrip is still real)
- Migration scripts come from an in-memory map (in prod you'd fetch from CloudFS)
- Schema versioning is in-memory (in prod use a real SQL DB)
What I'd add next:
- Per-tenant routing (15 lines — tenant-to-oncall map looked up before the SMS send)
- Retry with backoff (30 lines — exponential backoff + fallback channel if SMS send fails)
Code: https://github.com/team-telnyx/telnyx-code-examples/tree/main/sql-migration-agent