# Scaling Fresh Coffee Subscriptions With Event-Driven Fulfillment

A coffee subscription startup looks simple from the outside: customers choose a roast, set a cadence, and receive beans before they run out. Under the hood, the hardest technical problem is timing. Coffee is perishable, roasting capacity is finite, and fulfillment needs enough lead time to batch orders without shipping stale inventory.

## Modeling the Subscription Cycle

The core domain model should separate `subscription`, `shipment`, and `roast_batch`. A subscription describes customer intent, a shipment represents a committed delivery, and a roast batch tracks production capacity. This keeps the system from treating every recurring charge as an immediate warehouse task, which becomes expensive once customers pause, skip, or change preferences.

## Using Events Instead of Cron-Only Logic

A nightly cron job can generate upcoming shipments, but it should publish durable events rather than directly mutating every downstream system. Billing, roasting, inventory allocation, and fulfillment can then react independently. This gives the team room to retry failures, replay events, and add operational dashboards without rewriting subscription logic.

```yaml
shipment_window:
  generate_days_ahead: 7
  roast_lead_time_days: 2
  max_batch_size: 480
  retry_policy: exponential_backoff
```

## Operational Tradeoffs

The startup also needs practical guardrails. Address validation should happen before shipment creation, payment retries should not block unrelated orders, and roast planning should reserve capacity before labels are purchased. These details matter because customer trust depends less on clever personalization and more on beans arriving fresh and on schedule.

## What to Measure

Useful metrics include skipped shipments, failed payment recovery, roast batch utilization, delivery promise accuracy, and average bean age at delivery. If those numbers are visible to engineering and operations, the company can tune cadence recommendations, reduce waste, and scale without turning every fulfillment day into manual triage.