MDZelo
首页/Indie Hacker Guide/Webhook in Practice

Webhook in Practice

When building a SaaS product, you will soon meet webhooks. Payment success, subscription cancellation, email bounce, file processing completion, and third-party data sync are often delivered through webhooks.

A webhook looks like “the other system calls one of your endpoints,” but in production there are many traps: duplicate events, signature verification, timeouts, out-of-order delivery, retries, consistency, and debugging.

If you treat a webhook like a normal API, critical flows such as payment, orders, and permissions can break.

A Webhook Is an External System Notifying You

A normal API usually means you request another system. For example, you call a payment platform to create an order.

A webhook works in the opposite direction. After an event happens, the external system calls your endpoint. For example, after payment succeeds, the payment platform sends a request to /api/webhooks/payment to tell you the order is complete.

This means webhooks have several characteristics: the request comes from an external system, the timing is not controlled by you, the event may be sent more than once, it may arrive late, and it may be retried if your service fails.

Webhook design is not only about receiving the event. It is about handling it safely, reliably, and traceably.

Step 1: Use Separate Endpoints for Each Source

Do not put all webhooks into one generic endpoint.

Payment platforms, email services, file services, AI services, and data sync services all have different event structures, signature methods, and retry behavior. It is better to use a separate endpoint for each source.

Examples:

text
POST /api/webhooks/stripe
POST /api/webhooks/paypal
POST /api/webhooks/email
POST /api/webhooks/storage

Separate endpoints make signature verification, logs, debugging, and isolation much clearer.

Step 2: Verify Signature Before Processing

The biggest security rule is simple: do not trust webhook requests by default.

An attacker may fake payment success, subscription status, or file processing completion. If you only read the request body and skip signature verification, your endpoint can be abused.

Most mature services provide signature verification. You use the platform's secret to verify the raw request body and headers, confirming that the request really came from the provider.

Many webhook signature systems require the raw request body. If your framework parses the body before verification, the signature may fail. Check this carefully during integration.

Step 3: Store the Event First

After a webhook arrives, do not only process it in memory, and do not forget it after processing.

Store the event ID, source, event type, raw payload, received time, and processing status in the database. When problems happen later, you can see what was received, when it arrived, and what happened.

A simple event table can include:

text
id
source
event_id
event_type
payload
status
received_at
processed_at
error_message

Event storage is the foundation of traceable webhook handling.

Step 4: Make Handling Idempotent

Webhooks may be sent more than once. This is normal.

If your endpoint times out and the provider does not receive a success response, it may retry. Network issues can cause duplicates. Some platforms guarantee “at least once” delivery, not “exactly once.”

Never assume the same event arrives only once.

The common approach is to use the provider's event_id as a unique key. If the event was already processed, return success and do not create another order, send another email, or add credits again.

Payment and subscription webhooks require special care.

Step 5: Return Success Quickly

A webhook endpoint should not run long business logic synchronously.

If you generate reports, send many emails, or call multiple third-party services inside the endpoint, it may time out. When it times out, the provider may retry and create more pressure.

A safer flow is: verify signature, store the event, enqueue or mark it for processing, and return success quickly. The real business logic runs in a background worker.

The webhook endpoint receives and acknowledges. The business processor executes and retries.

Step 6: Dispatch by Event Type

One source may send many event types.

A payment system may send checkout.completed, invoice.paid, subscription.updated, and subscription.canceled. An email service may send delivered, bounced, and complained.

Do not handle everything in one giant if-else block. Split logic into handlers by event type.

text
checkout.completed -> activate order
invoice.paid -> renew subscription
subscription.canceled -> cancel subscription
email.bounced -> mark email as invalid

Each event becomes clearer and easier to test.

Step 7: Handle Out-of-Order Events

Webhooks may not arrive in the order you expect.

You may receive a cancellation event before an update event. An old status may arrive after a successful status. A late event may overwrite a newer local state.

To handle this, do not simply overwrite state based on the latest received event. Look at event time, the business state machine, and the current local state.

For critical business flows, query the provider's current true state before updating your local system.

A webhook is a notification, not always the final source of truth. When necessary, verify with the source system.

Step 8: Add Logs and Alerts

Webhook issues are hard to debug from user reports. A user may only say, “I paid but my account was not activated” or “the email failed.”

You need to quickly answer: did we receive the event, did signature verification pass, was the event stored, did processing succeed, what error happened, and was it retried?

Log at least source, event ID, event type, processing time, error message, and related business object.

For payment, subscription, and critical data sync webhooks, failures should trigger alerts.

Prepare Local Testing Tools

Webhooks come from external systems, so local development is not directly reachable.

Use a tunnel tool to expose your local service, or use the provider's CLI, test events, or replay feature.

During debugging, check three things: whether the request reaches your local service, whether signature verification passes, and whether the business result is correct.

Do not test webhooks for the first time after launch. Test them repeatedly in development and staging.

A Webhook Processing Flow

Use this flow:

text
1. Receive request
2. Read raw body
3. Verify signature
4. Parse event
5. Deduplicate by event_id
6. Store event
7. Return success quickly
8. Dispatch in background
9. Update business state
10. Log results and errors

If this flow is stable, most webhook scenarios become manageable.

Final Thoughts

A webhook is not a normal API. It is the bridge between an external system and your internal business state.

Reliable webhook design must include signature verification, idempotency, event storage, quick response, background processing, logs, and retries. For payment and subscription flows, do not skip these basics.

Next, we continue with login systems: How to Integrate OAuth Login.

评论

0

分享你对这一章的想法

还没有评论成为第一个分享想法的人。