Each ADR captures one load-bearing decision with a trade-off you can argue both sides of. They keep settled decisions from being silently re-litigated — and each one is a ready-made answer to "walk me through a hard technical decision."
Format: Status · Context · Decision · Consequences · Alternatives · Revisit-if.
Status: Accepted = decided & (being) implemented · Proposed = locked direction for a later phase.
| ADR | Decision | Status | Phase |
|---|---|---|---|
| 0001 | Redirect resolver is a separate service from the management API | Proposed | 2 (Day 8) |
| 0002 | Short codes via a Key Generation Service (pre-allocated base62, non-enumerable) | Proposed | 1 (Day 3) |
| 0003 | Hybrid edge KV + Spring Boot origin for resolve | Proposed | 2 (Day 8) |
| 0004 | Analytics off the hot path: fire-and-forget → stream → OLAP | Proposed | 1 (Day 6) |
| 0005 | Default 302 (temporary) redirect, not 301 | Accepted | 0 (Day 2) |
| 0006 | Multi-tenant custom domains + on-demand per-host TLS | Proposed | 3 (Day 10) |
| 0007 | ClickHouse (columnar OLAP) for click analytics | Proposed¹ | 1 (Day 6) |
| 0008 | Cache invalidation: write-through + explicit edge purge + short TTL | Proposed | 0→2 (Day 5/8) |
| 0009 | Safe-Browsing scan on create + aggressive rate limits | Proposed | 0 (Day 4) |
| 0010 | Smart routing at resolve time; A-B with sticky bucketing | Proposed | 3 (Day 11) |
| 0011 | Next.js App Router frontend, decoupled from the resolver | Accepted | 0 (Day 1) |
| 0012 | Flyway-owned schema; ddl-auto=validate |
Accepted | 0 (Day 1) |
¹ Postgres-first for the MVP; the ClickHouse split is the deliberate analytics-scale chapter.
Where they come from: 0001–0010 are the architecture-level decisions (mirrored from the project spec §7 and ARCHITECTURE.md §12); 0011–0012 are the concrete Day-1 implementation decisions already shipped in the scaffold.