← Back to news

The Valley of Webhooks

weli.dev|38 points|17 comments|by weli|Aug 5, 2026

The Valley of Webhooks

I have now constructed the exact same architecture three separate times, across three different organizations, integrating with three different third-party providers.

It is a ghost project; it never earns a formal name or a slot on the official product roadmap. Yet, the trajectory is always identical: you realize that the absolute truth regarding your users is stored in a database you don't control.

Whether it is identity providers for users, Stripe for billing, or an email service for bounce rates, your local application needs a mirror of that truth to function.

The Illusion of Simplicity

Initially, I convinced myself I was just building a simple endpoint. It's just one route to parse JSON and update a row; it'll take an afternoon.

In reality, the complexity grows in predictable, painful stages:

  1. Security: I had to implement signature verification because an unprotected endpoint that modifies data is essentially a security vulnerability.
  2. Idempotency: I added a deduplication table because providers guarantee "at-least-once" delivery, meaning the same event often arrives twice.
  3. Ordering: I implemented a buffer, because a membership.created event might arrive before the user.created event it references.
  4. Initialization: I built a bootstrap importer to fetch existing data, as webhooks only track changes after you subscribe. This required a complex locking mechanism to prevent race conditions with live events.
  5. The Safety Net: Finally, I wrote the reconciliation cron.

"I do not trust the copy I built, and I have no way to know when it’s wrong, so I will re-derive it from scratch every night, forever."

The Silent Failure

Data drift doesn't send an alert; it manifests as a support ticket. In one instance, a user had cancelled their plan months ago, but our system still listed them as active. A customer.subscription.deleted event had simply vanished in transit.

The provider's dashboard showed the event as "retried and dropped," and our logs showed nothing because the request never reached us. There was no alarm—just a discrepancy.

The Architecture of Frustration

Managing this across different providers is a nightmare of fragmented UI. Each has a unique way of handling secrets, registering endpoints, and separating test from live environments. Debugging becomes a "three-tab tour":

  • Tab 1: The provider's delivery logs.
  • Tab 2: Our internal application logs.
  • Tab 3: The provider's administrative dashboard.

By the third iteration, I stopped lying to myself. I budgeted for the entire stack—signatures, deduping, buffering, bootstrapping, and the 3 a.m. cron—from day one.

The Fundamental Misunderstanding

I realized that I wasn't actually handling notifications; I was attempting to reconstruct an ordered log.

The provider possesses the complete history (which they use to render their own dashboards). They shred that history into individual POST requests and fire them over a network that guarantees neither order nor delivery. I then try to glue those pieces back together.

It is like a jigsaw puzzle where the manufacturer:

  • Cuts up the image.
  • Mails pieces one by one.
  • Loses some in the mail.
  • Sends some twice.
  • Provides no picture on the box.

When the final image is wrong, the provider asks, "Which pieces are you missing?" I can't answer, because Missing Data=Unknown\text{Missing Data} = \text{Unknown}.

Notifications \neq Data Transfer

The core issue is the definition of a webhook: a notification that something happened.

FeatureNotification (Side Effect)Replication (Data Sync)
GoalTrigger an actionMaintain a mirror copy
OrderingUsually irrelevantCritical
Completeness"Best effort" is okayMust be 100%
RequirementFire-and-forgetVerifiable state

The term was coined by Jeff Lindsay in 2007. Early use cases were perfect fits:

  • GitHub hooks triggering a CI build.
  • Payment pings triggering a receipt email.

These are "side effects." If you forget to send a receipt, it's a nuisance; if you lose a "user deleted" event, your database is corrupted.

The "Checkbox" Trap

Webhooks became a standard API checkbox because they were the cheapest solution for both sides. However, the industry failed to distinguish between two very different jobs:

  • Trigger a side effect: (e.g., Ping a Slack channel).
  • Keep a copy of provider data correct: (e.g., Syncing subscription status).

We used a 2007 tool for a 2024 data problem and spent fifteen years building workarounds.

The Fitness Landscape

In evolutionary biology, the fitness landscape describes how populations evolve toward "peaks" (optimal designs).

Fitness Landscape Concept

The danger is the local optimum: a small hill that is better than its immediate surroundings. To reach a higher peak, a species must first cross a "valley" of designs that are temporarily worse. Evolution avoids this.

Using webhooks for replication is a local optimum. The "valley floor" is paved with the workarounds I've spent years building:

  • Exponential Backoff
  • Dead-letter Queues
  • Idempotent Handlers
  • 3 a.m. Reconciliation Crons

This is why specialized infrastructure has emerged. Svix exists so providers don't have to build the delivery engine; Hookdeck exists so consumers don't have to build the ingestion plumbing.