Handle subscription lifecycle events (created, updated, deleted) with idempotent, state-aware logic. Process only resources that need changes, and track subscription status separately from resource status.
Subscription events are noisy: retries, out-of-order delivery, and status transitions all happen in production. The safest posture is to treat every event as a diff, only touching resources that actually need a change.
This guide lays out concrete handling rules for created, updated, and deleted events, with implementation patterns, rationale, and an architecture that scales with retry storms.
PENDING resources and set subscription to active.SUSPENDED resources when status is active/trialing.ACTIVE resources when status is past_due/unpaid.canceled; leave resources as-is.IF subscription.created:
FOR EACH resource IN user_resources:
IF resource.status == PENDING:
→ Activate resource
→ Trigger activation workflow
ELSE:
→ Skip (already active or in different state)
SET subscription.status = 'active'
CLEAR subscription.date_suspended
IF subscription.updated:
IF new_status IN ['active', 'trialing']:
FOR EACH resource IN user_resources:
IF resource.status == SUSPENDED:
→ Reactivate resource
→ Trigger reactivation workflow
SET subscription.status = 'active'
CLEAR subscription.date_suspended
ELSE: // past_due, unpaid, etc.
FOR EACH resource IN user_resources:
IF resource.status == ACTIVE:
→ Suspend resource
→ Trigger suspension workflow
SET subscription.status = 'suspended'
IF subscription.date_suspended IS NULL:
SET subscription.date_suspended = NOW()
IF subscription.deleted:
CLEAR subscription.subscription_id
SET subscription.status = 'canceled'
// DO NOT modify resource statuses
// Resources remain in their current state (typically SUSPENDED)
// Manual cleanup or scheduled jobs can handle final deletion
Keep event handling predictable by sequencing validation, actions, and metadata updates. The flow below makes retries safe and isolates failures.
Webhook Receiver
↓
Event Router (created / updated / deleted)
↓
State Validator (check current resource states)
↓
Action Executor (activate / suspend / reactivate)
↓
Status Updater (update subscription metadata)
↓
Workflow Trigger (async jobs for provisioning)