Webhook Implementation Guides by Language and Framework
The complete developer hub for webhook implementation tutorials. Find guides for sending, receiving, and verifying webhooks in Node.js, Python, Go, and popular frameworks like Next.js, Django, and Express.
Webhook Implementation Guides by Language and Framework
Your central hub for webhook implementation tutorials. Whether you're building a webhook sender, integrating incoming webhooks, or implementing signature verification, find the right guide for your stack.
Table of Contents
- Use Cases
- Sending Webhooks by Language
- Receiving & Verifying Webhooks by Language
- Framework-Specific Guides
- Essential Concepts
- Quick Comparison
- Getting Started with Hook Mesh
Use Cases
Sending webhooks: Building a service that notifies external systems on events. Focus on reliability, retry logic, and signatures.
Receiving webhooks: Integrating with external services. Focus on signature verification, idempotency, and acknowledgment.
Both: Many applications send to customers while receiving from third-party services like Stripe or GitHub.
Sending Webhooks by Language
Building a webhook delivery system? These guides cover event generation, payload construction, signature creation, and delivery with retries.
Node.js | send-webhooks-nodejs.md
Production-ready delivery: async queuing (Bull, BeeQueue), HMAC-SHA256 signatures, exponential backoff, TypeScript support.
Best for: Real-time apps, startups.
Python | send-webhooks-python.md
Task queues (Celery), cryptographic signatures, Django/Flask integration, async delivery.
Best for: Data pipelines, enterprise apps.
Go | send-webhooks-go.md
Goroutine pools, native crypto/hmac, channel-based retries, memory-efficient handling.
Best for: High-volume systems, microservices.
Receiving & Verifying Webhooks by Language
Security first. These guides cover verification, processing, and reliability.
Node.js | receive-verify-webhooks-nodejs.md
Raw body parsing, timing-safe comparison, Express/Fastify middleware, async queuing.
// Express middleware for signature verification
app.post('/webhooks', express.raw({ type: 'application/json' }), async (req, res) => {
const signature = req.headers['x-webhook-signature'] as string;
const expectedSig = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET!)
.update(req.body)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSig))) {
return res.status(401).send('Invalid signature');
}
// Queue for async processing - respond immediately
await webhookQueue.add(JSON.parse(req.body));
res.status(200).send('OK');
});Best for: Express/Fastify apps, serverless.
Python | receive-verify-webhooks-python.md
Flask/Django implementations, constant-time comparison, Pydantic validation, Celery processing.
# Flask webhook receiver with signature verification
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Webhook-Signature')
payload = request.get_data() # Raw bytes, not parsed JSON
expected_sig = hmac.new(
os.environ['WEBHOOK_SECRET'].encode(),
payload,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected_sig):
return 'Invalid signature', 401
# Queue for background processing
celery_app.send_task('process_webhook', args=[payload.decode()])
return 'OK', 200Best for: Django/Flask apps, data pipelines.
Go | receive-verify-webhooks-go.md
net/http handlers, ConstantTimeCompare verification, structured logging, graceful shutdown.
// HTTP handler for webhook verification
func webhookHandler(w http.ResponseWriter, r *http.Request) {
signature := r.Header.Get("X-Webhook-Signature")
body, _ := io.ReadAll(r.Body)
mac := hmac.New(sha256.New, []byte(os.Getenv("WEBHOOK_SECRET")))
mac.Write(body)
expectedSig := hex.EncodeToString(mac.Sum(nil))
if subtle.ConstantTimeCompare([]byte(signature), []byte(expectedSig)) != 1 {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
// Queue for async processing
webhookQueue <- body
w.WriteHeader(http.StatusOK)
}Best for: Microservices, high-reliability systems.
Framework-Specific Guides
Next.js | webhooks-nextjs-hook-mesh.md
App Router/Pages Router patterns, raw body configuration, Edge runtime, Vercel optimization.
Best for: Full-stack React, Vercel.
Django | webhooks-django-hook-mesh.md
Class-based views, CSRF exemption, Django Signals, admin integration.
Best for: Enterprise apps, content platforms.
Express.js | webhooks-express-best-practices.md
Middleware ordering, router organization, error handling, rate limiting.
Best for: APIs, microservices.
Serverless | webhooks-serverless-lambda-vercel-cloudflare.md
AWS Lambda + API Gateway:
- 6MB request payload limit
- 30-second default timeout (configurable up to 15 minutes for async processing)
- Cold starts add 100-500ms latency
- Requires explicit binary media type configuration for raw body access
- Use Lambda async invocation for long-running processing
Vercel Serverless Functions:
- 10-second timeout for API routes (no configuration)
- Edge functions limited to 30 seconds
- Unlimited request size (body stored in memory)
- Automatic retry on timeout (use idempotency keys)
- Built-in analytics and logging dashboard
Cloudflare Workers:
- 30-second timeout (CPU limit, not wall-clock)
- Streams support for large payloads
- Global distribution by default
- No cold starts (always-warm)
- Durable Objects for state management and queuing
Cold start mitigation: Small packages, provisioned concurrency, pre-connection, bundling frameworks.
Best for: Event-driven apps, cost-sensitive deployments.
Common Pitfalls
Avoid these frequently encountered mistakes when building webhook systems.
Receiving Webhooks
1. Using parsed JSON body for signature verification
The signature is computed over the raw bytes, not the parsed object. Always verify against the raw request body before any parsing or transformation.
// Wrong - signature will never match
app.post('/webhooks', express.json(), (req, res) => {
const signature = computeSignature(JSON.stringify(req.body)); // Different bytes!
});
// Correct - use raw body
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const signature = computeSignature(req.body); // Original bytes
});2. Synchronous processing blocking the response
Webhook senders have strict timeouts (often 5-30 seconds). If your processing takes longer, you'll receive duplicate deliveries. Always respond immediately and process asynchronously.
3. No idempotency handling
The same webhook can arrive 2-5 times due to network issues, retries, or sender bugs. Store processed webhook IDs and check before processing.
4. Missing timestamp validation
Reject webhooks with timestamps older than 5 minutes to prevent replay attacks. Most providers include a timestamp in the signature computation.
Sending Webhooks
1. No retry with exponential backoff
Network failures are common. Implement retries with increasing delays (e.g., 1s, 5s, 30s, 2m, 10m) to handle transient failures without overwhelming failing endpoints.
2. Blocking on delivery
Never send webhooks synchronously in your request path. Use a queue (Redis, SQS, database) to decouple event generation from delivery.
3. Hardcoded secrets
Webhook signing secrets should be stored in environment variables or a secrets manager, never in code. Rotate secrets periodically.
4. No delivery logging
Without logs, debugging delivery failures is impossible. Log every attempt with: endpoint URL, response status, latency, and retry count.
Observability and Monitoring
Production webhook systems require comprehensive monitoring. Without visibility, you're flying blind when issues occur.
Key Metrics
| Metric | Description | Alert Threshold |
|---|---|---|
| Success Rate | Percentage of webhooks delivered successfully (2xx response) | < 95% over 5 minutes |
| P99 Latency | 99th percentile delivery time | > 10 seconds |
| Queue Depth | Number of webhooks waiting to be processed | > 10,000 messages |
| Signature Failures | Rate of incoming webhooks failing verification | > 1% of traffic |
| Retry Rate | Percentage of deliveries requiring retries | > 20% sustained |
| Dead Letter Queue Size | Webhooks that exhausted all retries | Any increase |
Structured Logging Requirements
What to log:
- Webhook ID and event type
- Endpoint URL (domain only, not full path with query params)
- HTTP response status code
- Request latency in milliseconds
- Retry attempt number
- Timestamp in ISO 8601 format
What NOT to log:
- Full webhook payload (may contain PII or sensitive data)
- Signing secrets or API keys
- Full endpoint URLs with authentication tokens
- Customer-specific identifiers without redaction
{
"level": "info",
"timestamp": "2026-01-20T14:32:00.000Z",
"webhook_id": "wh_abc123",
"event_type": "order.completed",
"endpoint_domain": "api.customer.com",
"status_code": 200,
"latency_ms": 145,
"attempt": 1
}Alert Configuration
Set up alerts for:
- Immediate: Dead letter queue receiving messages (something is broken)
- Warning: Success rate drops below 98% (degraded performance)
- Critical: Success rate drops below 90% (major outage)
- Anomaly: Sudden spike in signature failures (potential attack or misconfiguration)
Provider Response Time Requirements
When receiving webhooks from third-party services, your endpoint must respond within their timeout window or risk duplicate deliveries.
| Provider | Timeout | Retry Behavior | Notes |
|---|---|---|---|
| Stripe | 20 seconds | 8 retries over 3 days | Exponential backoff, status dashboard available |
| GitHub | 10 seconds | 3 retries | Retries at 10s, 60s, and 5 minutes |
| Shopify | 5 seconds | 19 retries over 48 hours | Aggressive initial retries |
| Twilio | 15 seconds | Configurable (0-5 retries) | Fallback URL supported |
| PayPal | 20 seconds | Up to 3 days | IPN simulator for testing |
| Slack | 3 seconds | 3 retries within 30 minutes | Rate limiting applies |
Key takeaway: Design your webhook receiver to respond within 3 seconds. Acknowledge immediately, then process asynchronously.
Essential Concepts
HMAC-SHA256 Signatures | hmac-sha256-webhook-signatures.md
Cryptographic authentication, timing-safe verification, header conventions, key rotation.
Idempotency | webhook-idempotency-guide.md
Idempotency keys, deduplication, handling out-of-order delivery, idempotent operations.
Security Best Practices | webhook-security-best-practices.md
IP allowlisting, payload encryption, rate limiting, audit logging.
Quick Comparison
| Stack | Sending | Receiving | Best Use Case |
|---|---|---|---|
| Node.js | Excellent async support, huge ecosystem | Native JSON handling, middleware flexibility | Real-time apps, startups, full-stack JS |
| Python | Clean syntax, great libraries | Strong validation tools, Django/Flask integration | Data pipelines, enterprise apps |
| Go | High throughput, low memory | Excellent performance, type safety | High-volume systems, microservices |
| Next.js | API routes with React frontend | Vercel-optimized, Edge support | Full-stack React, modern web apps |
| Django | Batteries-included approach | Class-based views, admin tools | Enterprise, content platforms |
| Express | Maximum flexibility | Fine-grained control | Custom APIs, microservices |
| Serverless | Auto-scaling, pay-per-use | Global distribution, no servers | Event-driven, variable traffic |
By Project Type
- SaaS → Node.js/Python for sending, framework of choice for receiving
- E-commerce → Next.js/Django full-stack or serverless
- Fintech → Go for reliability
- Startup MVP → Node.js + Express for speed
- Enterprise → Python/Django for maintainability
Framework Version Requirements
| Framework | Min Version | Current Stable | Notes |
|---|---|---|---|
| Node.js | 14 LTS | 22 LTS | Use async/await; Node 18+ recommended for native fetch API |
| Express.js | 4.16 | 4.21 | Express 5.x in beta, recommended for native promises |
| Next.js | 13.4 | 16 | App Router required for Edge Function webhook support |
| Python | 3.7 | 3.13 | Async support requires 3.7+; use 3.10+ for better type hints |
| Django | 4.0 | 5.0 | Async views added in 3.1; 4.0+ required for webhooks |
| Flask | 2.0 | 3.x | Use 2.2+ for improved async support |
| Go | 1.16 | 1.23 | Standard library; no major version requirements |
Key takeaway: Use the latest LTS version of your runtime and framework for best webhook support and security patches.
Getting Started with Hook Mesh
Hook Mesh handles webhook infrastructure so you don't have to.
Sending: Retries, signatures, analytics, multi-tenant management.
Receiving: Verification, idempotency, replay tools, type-safe SDKs.
Install the SDK
# Node.js
npm install @hookmesh/sdk
# Python
pip install hookmesh
# Go
go get github.com/hookmesh/hookmesh-goSend Your First Webhook
import { HookMesh } from '@hookmesh/sdk';
const hookmesh = new HookMesh({ apiKey: process.env.HOOKMESH_API_KEY });
await hookmesh.send({
endpoint: 'https://api.customer.com/webhooks',
event: 'order.completed',
payload: { orderId: '12345', total: 99.99 }
});Ready to simplify your webhook infrastructure? Start free with Hook Mesh and ship reliable webhooks in minutes, not weeks.
Have questions about webhook implementation? Join our Discord community or check our documentation.