Lemon Squeezy webhooks arrive unsigned—here's the risk
The server log scrolls past midnight, POST requests stacking up from a domain you half-recognise. The payload looks right—subscription created, customer billed—but nothing in the header proves it came from your payment processor and not a curious teenager with Postman and your endpoint URL.
Lemon Squeezy webhooks carry HMAC signatures you probably aren’t checking
Every inbound webhook includes a cryptographic signature; ignoring it means anyone can forge subscription events.

Lemon Squeezy sends an X-Signature header with every webhook. That header contains an HMAC-SHA256 hash of the request body, signed with a secret only you and Lemon Squeezy know. If the signature you compute server-side matches the one in the header, the payload is genuine. If it doesn’t match, someone spoofed the request—and your application should reject it before touching the database.
Most operators who add Lemon Squeezy to a Next.js API route or Express endpoint skip signature verification entirely. The webhook fires, the handler parses JSON, the database writes a new subscription row, and everything works—until an attacker discovers your /api/webhooks/lemon-squeezy endpoint and starts sending fake “subscription_created” events with invented email addresses or inflated plan IDs. Without signature validation, your application has no way to distinguish legitimate events from fabricated ones. The liability isn’t theoretical: public endpoint URLs leak in client-side code, old commit logs, and misconfigured serverless logs.
Validating the signature requires fewer than ten lines of code in Node, Python, or PHP: retrieve the signing secret from your Lemon Squeezy dashboard, hash the raw request body with crypto.createHmac or equivalent, compare the result to the header value using a timing-safe comparison function, and return 401 if they don’t match. The pattern is identical to Stripe’s webhook verification, and the stakes are the same—skip it and you’re trusting the internet to play fair with your revenue data.
RELATED INFRASTRUCTURE
Stripe and Paddle retry failed webhooks differently—here’s how long you have
Once you verify signatures, the next failure mode is a handler that crashes or times out. Stripe retries failed webhooks for up to three days with exponential backoff; Paddle’s retry window is shorter and the intervals differ. If your server is down for six hours during a product launch, you may lose subscription lifecycle events entirely—or receive them out of order when the queue drains. Understanding each processor’s retry logic tells you how much downtime you can tolerate before manual reconciliation becomes necessary.
TACTIC
WordPress staging sync direction matters more than the clone button
Payment webhook handlers often live in a WordPress plugin or theme functions file. Most managed hosts offer one-click staging environments, but cloning production down to staging is only half the workflow. When you’re testing webhook endpoint changes, you need to push code up from staging to production without overwriting live subscription data. Knowing when to pull database snapshots down versus pushing plugin files up prevents the nightmare scenario where a staging sync wipes your production orders table because you clicked the wrong directional arrow in Kinsta or WP Engine.
WORTH READING
Postmark’s message streams separate transactional reputation from broadcast
If you’re sending both Lemon Squeezy purchase receipts and weekly newsletter broadcasts through the same SMTP provider, a spam complaint on your newsletter can hurt deliverability for your transactional emails. Postmark’s message streams feature lets you configure separate sending reputations: one stream for order confirmations and password resets, another for marketing sends. Each stream tracks bounces, complaints, and engagement independently, so a bad broadcast doesn’t poison your receipt deliverability. The feature costs nothing extra, but knowing when to split streams—and when a single default stream is sufficient—depends on your sending volume and list hygiene.
Know someone who would like this? Forward today’s email — every operator we reach is one closer to running an online business with a little less friction.