Most business automation tools work by polling: every few minutes, they check whether something has changed and act on it if so. A new row appears in a spreadsheet — the automation tool checks, sees it, and triggers an action 5 minutes later. A payment succeeds in Stripe — the tool polls, notices the new event, and fires a webhook to your fulfillment system 3 minutes after the payment was captured.
For many use cases, this delay is acceptable. For others, it's a problem. A customer pays for a digital product and waits 3 minutes for their download link. A critical business alert fires 5 minutes after the underlying event that should have triggered it. An inventory system responds to a large order 10 minutes too late to prevent an oversell.
Webhook-driven pipelines solve this. When systems communicate via webhooks, events trigger actions in milliseconds. The payment captures → the webhook fires → the fulfillment action executes → the customer receives their download link, all within seconds. This is the architecture of modern real-time business automation.
A webhook is an HTTP request that one system sends to another when a specific event occurs. Unlike API polling (where your system asks "has anything changed?"), webhooks push notifications ("something just happened"). The sender makes a POST request to a URL you specify, including data about the event in the request body.
Examples: Stripe fires a webhook when a payment succeeds or fails. GitHub fires a webhook when code is pushed to a repository. Shopify fires a webhook when an order is created or updated. Typeform fires a webhook when a form is submitted.
Your webhook receiver — the URL that accepts these requests — processes the event and takes whatever action is appropriate: update a database, trigger another API call, send an email, log the event, or any combination.
Payment processors are the most common webhook source for e-commerce and SaaS businesses. Events you'll handle:
payment_intent.succeeded — trigger digital product delivery, activate subscription, send receiptinvoice.payment_failed — notify customer, downgrade account, trigger dunning sequencecustomer.subscription.deleted — revoke access, trigger win-back campaign, update CRMcheckout.session.completed — add customer to fulfillment queue, trigger onboarding email sequenceGetting these right matters. A failed payment that doesn't trigger a dunning sequence leaks revenue. A successful payment that doesn't trigger product delivery creates a support ticket.
When a prospect submits a contact form, you want several things to happen simultaneously: create a CRM contact, assign a sales rep, send a confirmation email to the prospect, post a notification to Slack, and possibly trigger a lead scoring evaluation. Done via polling, these happen sequentially with delays. Done via a webhook pipeline, they happen in parallel within seconds.
When a deal closes in your CRM, trigger: an onboarding email sequence, a task for the customer success team, an invoice in your accounting software, and a Slack message to the team. When a support ticket is escalated, trigger: an immediate notification to the relevant team lead, an update to the customer account record, and a monitoring alert if the SLA is at risk.
Code deployed to production? Trigger an automated smoke test, update your status page, and notify relevant team members. A monitoring alert fires? Trigger an incident response workflow, create a ticket, and page the on-call engineer. These automation patterns require real-time event processing that polling can't provide.
The basics of a webhook are simple. Building one that's reliable in production requires more care.
Webhook endpoints are public URLs. Anyone can send a POST request to them. Legitimate webhook providers (Stripe, GitHub, Shopify) sign their requests with a secret key. Your handler should verify this signature before processing. A request without a valid signature should be rejected. Skipping this step is a security vulnerability.
Webhook senders expect a fast HTTP response (typically under 5 seconds). If your processing logic takes longer — database writes, calls to slow APIs, complex computations — you'll get delivery timeouts and duplicate events. The pattern: acknowledge the webhook immediately with a 200 response, queue the event for async processing, and handle it in a background worker.
Webhook providers retry delivery if they don't receive a successful response. This means you'll sometimes receive the same event multiple times. Your handler must be idempotent — processing the same event twice should produce the same result as processing it once. Use the event ID (provided by the sender) to deduplicate: if you've already processed event ID X, ignore the retry.
Some webhook events will fail to process — a downstream API is unavailable, a database write fails, unexpected data format. Failed events should go to a dead-letter queue for investigation and retry, rather than being silently dropped. A custom webhook pipeline should include proper error handling and observability from the start.
Webhook pipelines are asynchronous and event-driven, which makes debugging harder than synchronous code. Log every event received, every processing step, every error, and every output action. When something goes wrong — and it will — you need a complete audit trail to understand what happened and replay the correct behavior.
Automation platforms like Zapier and n8n can receive webhooks and trigger actions. For simple cases, this is sufficient. Build a custom webhook pipeline when: you need sub-second response times, you need complex processing logic or conditional routing, you need full observability and custom retry behavior, or you're handling sensitive data that shouldn't pass through third-party infrastructure.
At Refitted, we build custom workflow automation systems including webhook pipelines with proper reliability infrastructure. Tell us about the event flows you need to handle and we'll design the right architecture.
We build custom websites, web apps, and automated Google Sheets systems. Tell us what you need and we'll handle the rest.
Get Started