# Exercise 1: Assign the Right Guarantee to Six Pipelines

For each pipeline: (a) state the guarantee you need — at-most-once, at-least-once, or effectively-once (at-least-once + idempotence) / Kafka EOS; (b) give the exact **producer** settings, (c) the **consumer** ack/commit strategy, and (d) the **idempotency mechanism** if any. Base every choice on `broker_delivery_guarantees_theory.md`.

## Pipelines

1. **Server CPU metrics** — 200 hosts send CPU % every 5 seconds to a dashboard. Throughput matters; a few missing points are invisible.
2. **Password-reset emails** — `PasswordResetRequested` events trigger an email via a third-party provider whose API accepts an `Idempotency-Key` header.
3. **Wallet top-ups** — `TopUpSucceeded { userId, amount, paymentId }` events credit a user's wallet balance in PostgreSQL.
4. **Clickstream sessionization** — a Kafka Streams app reads raw clicks from `clicks`, groups them into sessions, and writes to `sessions` (also Kafka).
5. **Search indexing** — `ProductUpdated { productId, version, ... }` events update an Elasticsearch document.
6. **Audit log for compliance** — every admin action must appear in the audit store; regulators accept duplicates (they're deduplicated in reports) but never gaps.

## Deliverables

For each pipeline, a short block:

```
Pipeline N:
  guarantee:
  producer:   (acks / idempotence / confirms / outbox?)
  consumer:   (ack/commit before or after processing? auto-commit?)
  idempotency:(none / dedup table / natural / provider key / version check / Kafka EOS)
  why:
```

Then answer:

7. Pipeline 3's consumer is written as:
   ```ts
   if (await db.processed.exists(event.paymentId)) return;
   await db.wallets.increment(event.userId, event.amount);
   await db.processed.insert(event.paymentId);
   ```
   Describe the crash that still double-credits, and rewrite it so it can't.
8. Why does Kafka EOS solve pipeline 4 but **not** pipeline 2, even if both consume from Kafka?

## Requirements Checklist

- [ ] 1 → at-most-once (or relaxed at-least-once), `acks=1`/`0`, auto-commit acceptable, no dedup.
- [ ] 2 → at-least-once; consumer commits after the provider call; idempotency via the provider's `Idempotency-Key` = event id.
- [ ] 3 → effectively-once: `acks=all` + idempotent producer (+ outbox on the producing side); consumer commits after the DB transaction; dedup row inserted **in the same transaction** as the balance update (unique constraint on `paymentId`).
- [ ] 4 → Kafka EOS: transactional producer, offsets sent to the transaction, `read_committed` downstream.
- [ ] 5 → at-least-once with a **version check** (external versioning in Elasticsearch / `version_type=external`) so duplicates and out-of-order events are harmless.
- [ ] 6 → at-least-once with durable produce (`acks=all`, `min.insync.replicas=2`), commit after the write is durable; duplicates explicitly acceptable.
- [ ] Q7 identifies the crash between `increment` and `insert` (redelivery re-credits) and fixes it with a single transaction or `INSERT ... ON CONFLICT DO NOTHING` gating the increment.
- [ ] Q8: the email is an external side effect outside the Kafka transaction; a crash after sending but before commit re-sends.
