payment-webhook-idempotency
Skill10 starsChanged 6 months agoMITView on GitHub
Use when Stripe or payment webhooks fire twice, need duplicate event handling, stripe_webhook_events table, ordering, or safe retries. Not for first-time webhook setup without idempotency concerns (use stripe-payment-webhooks).
In this repository56 other files it gives its agents.
- accessibility-passSkill
- analytics-eventsSkill
- api-error-handlingSkill
- audit-logging-backendSkill
- background-jobs-and-cronSkill
- dark-mode-and-themingSkill
- dashboard-charts-rechartsSkill
- edge-functions-and-webhooksSkill
- email-and-notificationsSkill
- error-states-and-empty-uiSkill
- feature-flags-and-togglesSkill
- file-upload-storageSkill
- i18n-multi-languageSkill
- lovable-prompting-playbookSkill
- lovable-ship-checklistSkill
- migration-playbookSkill
- multi-tenant-backendSkill
- onboarding-copySkill
- optimistic-updatesSkill
- payment-failed-and-recoverySkill
- payment-webhook-testingSkill
- performance-budgetSkill
- pg-cron-recipesSkill
- pg-cron-scheduled-jobsSkill
- pg-cron-with-pg-net-edgeSkill
- postgres-full-text-searchSkill
- postgres-triggers-and-functionsSkill
- pricing-and-billingSkill
- programmatic-seo-content-qualitySkill
- programmatic-seo-pagesSkill
- rate-limiting-edgeSkill
- realtime-and-subscriptionsSkill
- refactor-safe-diffSkill
- release-notesSkill
- seo-core-web-vitalsSkill
- seo-landing-pageSkill
- seo-meta-tags-spaSkill
- seo-sitemap-generationSkill
- seo-ssr-and-prerenderingSkill
- seo-structured-dataSkill
- server-input-validationSkill
- shadcn-patternsSkill
- soft-delete-and-archivingSkill
- stripe-one-time-payment-webhooksSkill
- stripe-payment-webhooksSkill
- supabase-auth-flowsSkill
- supabase-database-designSkill
- supabase-rls-and-authSkill
- support-replySkill
- tanstack-infinite-queriesSkill
- tanstack-mutations-and-invalidationSkill
- tanstack-prefetch-and-hydrationSkill
- tanstack-query-alternativeSkill
- tanstack-router-data-loadersSkill
- tanstack-start-server-routesSkill
- typed-api-hooks-formsSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 46
If work fails after partial writes, prefer:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Payment webhook idempotency
Stripe retries webhooks on non-2xx, slow responses, or network blips. Handlers must be safe to run multiple times for the same event.id.
Rules
- Insert
event.idfirst (or check existence) before side effects. - On duplicate
event.id, return 200 immediately — do not re-grant credits or extend subscription twice. - Side effects (DB upsert, emails, credits) must be upserts keyed by stable IDs (
subscription_id,payment_intent_id), not blind inserts.
Table
create table public.stripe_webhook_events (
id text primary key,
type text not null,
livemode boolean,
processed_at timestamptz not null default now()
);
-- RLS: no client access; edge function uses service role only
alter table public.stripe_webhook_events enable row level security;
-- no policies for anon/authenticatedHandler flow
receive event
→ verify signature
→ if event.id exists in stripe_webhook_events → 200 OK (duplicate)
→ begin logical work
→ upsert subscription / order (idempotent on stripe_subscription_id)
→ insert stripe_webhook_events
→ 200 OKIf work fails after partial writes, prefer:
- Transaction where possible, or
- Compensating upsert on retry, or
- Insert event id only after success (accept rare double-work on crash — mitigate with unique constraints on business keys)
Unique constraints (business layer)
alter table public.subscriptions
add constraint subscriptions_stripe_sub_id_unique unique (stripe_subscription_id);
create table public.orders (
id uuid primary key default gen_random_uuid(),
stripe_payment_intent_id text unique,
user_id uuid not null,
amount_cents int not null,
status text not null
);Ordering
Events may arrive out of order (subscription.updated before checkout.session.completed). Upsert from latest Stripe object via API retrieve when unsure, or handle both paths to the same upsert function.
Avoid
insert into credits (amount) values (100)without idempotency key per event.- Returning 500 after successfully granting access (causes retry + duplicate grant).
- Deleting webhook event rows in production.
Checklist
- Primary key = Stripe
event.id - Duplicate returns 200
- Business tables have unique Stripe IDs
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

