This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry.
Project Overview
supermarket--bot is a WhatsApp order bot written in Go, built for small businesses to take orders directly through WhatsApp. It handles the full order flow — Twilio for messaging, Paystack for live payments, and Cloudinary for product image uploads — plus an admin dashboard for managing orders. I was preparing to demo it to a restaurant client when this bug hit.
Bug Fix or Performance Improvement
The night before a client demo, a routine deploy to Railway stopped going live. Every deploy failed its healthcheck and got killed. No error in the app itself — it just never came up healthy.
I assumed it was a networking/port-binding problem, since that's a classic Docker + Railway gotcha. I spent a few hours chasing that theory before discovering the real bug: my app's boot sequence (connecting to Postgres on cold start) was taking longer than Railway's default 30-second healthcheck window. Railway wasn't rejecting an unreachable app — it was killing a container that hadn't finished booting yet. The fix ended up costing the client demo a two-day delay.
Code
Here's the chronological trail of the debugging session — including the wrong turns, which I think are worth showing:
fix port — changed hardcoded EXPOSE 8080 to EXPOSE $PORT in the Dockerfile
let railway set port — removed EXPOSE entirely, since Dockerfile EXPOSE resolves at build time and can't read Railway's runtime $PORT
add railway config — added explicit railway.toml with healthcheck path
bind to 0.0.0.0 — made the bind address explicit (in hindsight, functionally identical to what was already there)
debug port — added a log line to confirm Railway was injecting $PORT correctly (it was — this ruled out the networking theory entirely)
increase healthcheck timeout — the actual fix: bumped healthcheckTimeout from 30s to 60s
increase timeout — bumped it again to 120s with a retry-on-failure restart policy
Full diff: https://github.com/Gbolaww/supermarket--bot/compare/b30254e~1...c2d09b1
My Improvements
The interesting part of this bug wasn't the fix itself — it was how long I spent solving the wrong problem. Every symptom (deploy fails, healthcheck red, container restarts) looked like a networking issue, and Docker/Railway's EXPOSE and port-binding quirks are common enough that it was a reasonable first guess. But EXPOSE only matters at build time, and Go's ":8080" already binds all interfaces — neither of those theories held up once I added a debug log and saw the port was correct all along.
The real fix was config, not code: my healthcheck window needed to match my app's actual cold-start time, not an assumed one. Once healthcheckTimeout was long enough to cover the real DB-connect duration, the deploy went green on the first try.
Best Use of Sentry
To make this bug visible instead of a mystery next time, I went back and instrumented the exact code path that caused it — the database connection during boot — using sentry-go's distributed tracing. I wrapped the DB connect step in a db.connect span with a child db.ping span, wired Sentry's HTTP middleware across all routes, and added an env-var-controlled artificial delay (SIMULATE_SLOW_BOOT_SECONDS) so I could reproduce the original slow-boot failure on demand.
Instrumentation diff: https://github.com/Gbolaww/supermarket--bot/commit/ec097c0
Reproducing the original failure — a simulated 35-second slow boot, the kind of delay that would blow past a 30s healthcheck window. Sentry flagged it automatically as 296% slower than average:
The healthy boot — same span, no artificial delay, 249.23ms, flagged 97% faster than average:
Side by side, this is exactly the signal that would have caught the original bug in minutes instead of a multi-hour debugging session — a slow-boot span, automatically flagged as anomalous, instead of a healthcheck failure with zero visibility into why.


Top comments (0)