My webhook catcher silently dropped the first 160 of 260 test events - FIFO eviction hid the failure I needed
The Problem
I built a small ephemeral webhook receiver to make integration testing painless: create a singleβuse HTTPS URL, catch whatever a platform POSTs at it, read the events back. I spec’d it to store up to 100 events per hook. Then I used my own tool to debug a bulk GitHub integration and it bit me. I pointed 40 repos’ worth of push notifications at one catch URL - a CI job fanned out, and 260 deliveries landed within a minute. When I read the events back, I had the last 100, all identical successes. The very first deliveries - including the one with a malformed payload my handler choked on - had been silently evicted. The buffer was FIFO: newest in, oldest out, no error, no counter. I nearly concluded the bug was intermittent because the evidence of the first occurrence was gone. Classic blind spot. Keeping the tail is fine for “did anything arrive?” checks, but the event you’re actually debugging is almost always the FIRST anomaly, and FIFO deletes exactly that.
FIFO Buffer Design
- Capacity: 100 events per hook
- Policy: FIFO (newest in, oldest out)
- No error reporting or counter for dropped events
Fixes Shipped
- The read response now includes
received_totalanddropped, so truncation is never silent again. - I learned that the delivery count is itself diagnostic: 260 events told me the fanβout worked, and zero of them fired twice, which told me every delivery got a fast 2xx - no senderβside retries polluting the buffer.
- When I expect a burst now, I read back per batch instead of at the end.
Additional Considerations
One more thing worth knowing if you build a catcher: GitHub fires a ping event the moment you register the URL, before any real test data. It occupies a buffer slot early - harmless at capacity 100, but if you’re counting events precisely, don’t be surprised by it.
The Webhook Catch API
I packaged the receiver as the Webhook Catch API ( https://x402.freeq.one/tools/webhook_catch.html ) - a singleβuse HTTPS URL that accepts any POST for up to 24 hours, with events read back when you’re ready.
Lessons Learned
Building it taught me that a test double’s storage policy is a real design decision, not an afterthought: what it keeps - and what it quietly throws away - shapes what you’re able to learn.
Top comments (0)
Comments
No comments yet. Start the discussion.