# Brewing a Reliable Coffee Subscription Platform

A coffee subscription startup looks simple from the outside: customers choose a roast, select a delivery schedule, and receive fresh beans. Behind that experience is a scheduling system that must coordinate recurring payments, inventory, roasting capacity, and shipping deadlines. Our first version treated subscriptions as ordinary orders with a future date, but this approach became fragile as customers paused deliveries, changed plans, or updated addresses hours before fulfillment.

## Modeling Subscriptions as Schedules

We separated the long-lived subscription from the orders it generates. A subscription stores customer preferences and cadence, while each shipment becomes an immutable order containing a snapshot of the selected coffee, price, address, and tax calculation. A daily worker finds subscriptions due for renewal and creates orders using an idempotency key derived from the subscription ID and billing date. This prevents duplicate shipments when a job retries after a timeout.

```yaml
renewal_worker:
  schedule: "0 5 * * *"
  batch_size: 250
  retry_limit: 5
  lock_ttl_seconds: 300
```

## Keeping Inventory Honest

Coffee inventory is time-sensitive because green beans, roasted beans, and packaged units represent different stages of availability. Instead of decrementing stock when a subscription renews, we reserve forecast capacity seven days ahead and commit inventory when the fulfillment batch closes. This gives the operations team enough warning to adjust roast plans while still allowing customers to modify upcoming deliveries.

## Handling Payments Without Blocking Fulfillment

Payment processing runs asynchronously from order creation. Orders begin in a `payment_pending` state, and signed webhook events move them to `paid` or `payment_failed`. Webhook handlers record provider event IDs before changing state, making repeated events harmless. Failed payments enter a short recovery window with automated retries, while inventory reservations remain active until the order succeeds or expires.

## Observability and Practical Tradeoffs

The most useful production metrics are renewal lag, duplicate-prevention hits, payment recovery rate, inventory reservation failures, and the number of orders approaching their shipping cutoff. Structured logs include subscription and order IDs, but exclude customer details and payment data. This architecture adds more states than a basic recurring checkout flow, yet it gives support and operations teams a clear explanation for every delayed, changed, or canceled bag of coffee.