Skip to content
Decision Log
← Home
ADR examples

Real architecture decision records

6 example ADRs covering database, auth, frontend, and infrastructure decisions. Use these as templates for structuring your own.

6 decisions
ADR-001Adopt Postgres over DynamoDB for analytics
Accepted
ADR-002Migrate authentication to OAuth 2.0 with PKCE
Accepted
ADR-003Adopt React Query for client-side data fetching
Accepted
ADR-004Switch to pnpm for monorepo package management
Proposed
ADR-005Adopt Zod for API request validation
Accepted
ADR-006Use JWT sessions instead of Redis-backed sessions
Superseded
ADR-0012024-03-15Review: 2024-09-15
databaseanalyticsbackend
Accepted

Adopt Postgres over DynamoDB for analytics

Problem

Analytics queries are becoming complex and DynamoDB makes aggregation difficult without expensive scan operations. The team spends significant time working around its limitations.

Options
  1. Continue with DynamoDB and build a query layer
  2. Introduce Postgres for analytics workloads
  3. Move to a managed data warehouse (Redshift, BigQuery)
Decision

Introduce Postgres as the analytics database while keeping DynamoDB for transactional workloads. The team has existing Postgres expertise and the data volume does not yet justify a full data warehouse.

Trade-offs

Operational overhead increases (one more database to manage). Querying flexibility improves significantly. Risk of schema drift between transactional and analytics stores must be managed with an ETL process.

ADR-0022024-01-08Review: 2024-07-08
authsecuritybackend
Accepted

Migrate authentication to OAuth 2.0 with PKCE

Problem

The current session-based auth stores tokens in cookies with insufficient rotation. A security audit flagged the implementation as vulnerable to CSRF and token theft. We need a modern auth approach that supports third-party integrations.

Options
  1. Patch the current cookie-based session system
  2. Adopt OAuth 2.0 with Authorization Code + PKCE
  3. Use a managed auth provider (Auth0, Clerk)
Decision

Implement OAuth 2.0 with Authorization Code + PKCE. This eliminates the CSRF risk, supports future third-party integrations, and keeps auth logic in-house rather than adding a paid vendor dependency.

Trade-offs

Implementation complexity is higher than patching. The team needs to handle token refresh, revocation, and key rotation. Long-term this is the right architecture, but the migration has a ~3-week window risk.

ADR-0032024-02-20Review: 2024-08-20
frontendreactdata-fetching
Accepted

Adopt React Query for client-side data fetching

Problem

Custom data fetching hooks have grown inconsistent across the app — some cache, some don't, loading and error states are handled differently everywhere, and there is no built-in way to invalidate stale data. This causes UX bugs and maintenance burden.

Options
  1. Standardise the custom hook pattern with a shared utility
  2. Adopt TanStack Query (React Query)
  3. Move to SWR for a lighter-weight option
Decision

Adopt TanStack Query v5 as the standard data-fetching layer. It provides caching, background refetching, optimistic updates, and consistent loading/error states out of the box. The API is stable, well-documented, and the ecosystem is large.

Trade-offs

Adds a dependency and requires migrating existing hooks incrementally. SWR would have been lighter but lacks mutation handling and devtools. The migration can be done feature-by-feature over 4–6 weeks with no big-bang rewrite.

ADR-0042024-04-10Review: 2024-05-10
infrastructuredevtoolsmonorepo
Proposed

Switch to pnpm for monorepo package management

Problem

npm is causing hoisting conflicts between packages in the monorepo, resulting in phantom dependencies and inconsistent installs in CI. Install times have grown to 4+ minutes. We need a package manager designed for monorepo workspaces.

Options
  1. Stay on npm, add a `.npmrc` to disable hoisting
  2. Migrate to pnpm with workspace support
  3. Migrate to Yarn Berry with Plug'n'Play
Decision

Under review. Leaning toward pnpm — it uses hard links to avoid duplication, enforces strict dependency boundaries, and drops install time to under 90 seconds in benchmarks. Yarn Berry's PnP mode has known compatibility issues with some tooling.

Trade-offs

Requires team onboarding and updating CI/CD scripts. All developers need pnpm installed globally. PnP compatibility issues are avoided, but pnpm's strict mode may surface phantom dependencies that were silently working before.

ADR-0052023-11-03Review: 2024-05-03
backendapivalidationtypescript
Accepted

Adopt Zod for API request validation

Problem

Request validation is ad-hoc — some endpoints validate manually, others trust the client. TypeScript types only enforce shape at compile time; runtime validation is missing. This led to two production incidents where malformed payloads caused 500 errors.

Options
  1. Write a shared validation utility using manual type guards
  2. Adopt Zod for schema-based validation
  3. Use Joi (established but no TypeScript-first design)
Decision

Adopt Zod as the standard validation library. Schemas are defined once and produce both runtime validation and inferred TypeScript types, eliminating the drift between types and validation logic. All new endpoints must define a Zod schema.

Trade-offs

Bundle size increases by ~13 KB gzipped. Existing endpoints must be migrated progressively. The tradeoff is strongly in Zod's favour — the type inference alone eliminates an entire class of bugs.

ADR-0062023-06-15Review: 2023-12-15
authinfrastructurebackend
Superseded

Use JWT sessions instead of Redis-backed sessions

Problem

Redis session storage adds an infra dependency and latency on every authenticated request. As traffic grows, the Redis cluster cost has become significant. We evaluated moving to stateless JWTs.

Options
  1. Keep Redis sessions with connection pooling
  2. Move to short-lived JWTs (15 min) with refresh tokens
Decision

Move to short-lived JWTs with refresh tokens stored in HttpOnly cookies. Eliminates the Redis dependency for sessions. Access tokens expire quickly to limit exposure.

Trade-offs

Token revocation becomes harder — a compromised access token is valid until expiry. Refresh token rotation mitigates but does not eliminate this. Accepted as a reasonable tradeoff at the time.

Superseded by ADR-002 — Migrate authentication to OAuth 2.0 with PKCE

Start logging your own decisions

Free to start. No credit card required.

Get started free →