# Architecture Decision Record

> ADR format and methodology for documenting significant technical decisions with context, alternatives considered, and consequences. Use when making or documenting architectural decisions. Use when this capability is needed.

- Skill: `tomevault-io/architecture-decision-record-4` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/architecture-decision-record-4`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/architecture-decision-record-4/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/architecture-decision-record-4

---


# Architecture Decision Records

## ADR Template

Every ADR follows this structure:

```markdown
# ADR-NNN: Title of the Decision

## Status

[Proposed | Accepted | Deprecated | Superseded by ADR-NNN]

## Context

What is the issue that we are seeing that motivates this decision or change?
Describe the forces at play (technical, political, social, project-related).
Include any constraints, requirements, or assumptions.

## Decision

What is the change that we are proposing and/or doing?
State the decision in full sentences using active voice.
Be specific about what will be done.

## Consequences

What becomes easier or more difficult because of this decision?
List both positive and negative consequences.
Include any follow-up actions required.
```

## When to Write an ADR

Write an ADR for any decision that meets one or more of these criteria:

| Trigger                                    | Example                                         |
|--------------------------------------------|-------------------------------------------------|
| Adopting or replacing a technology         | Switching from REST to GraphQL                  |
| Changing an architectural pattern          | Moving from monolith to microservices           |
| Infrastructure decisions                   | Choosing a cloud provider or database           |
| API design choices                         | Choosing pagination strategy                    |
| Authentication/authorization strategy      | Adopting OAuth2 with PKCE                       |
| Data model decisions                       | Choosing between SQL and NoSQL                  |
| Cross-cutting concerns                     | Standardizing error handling or logging         |
| Process or convention changes              | Adopting conventional commits                   |
| Build/deployment decisions                 | Choosing CI/CD platform                         |
| Decisions that are hard to reverse         | Anything with significant migration cost        |

### Do NOT Write an ADR For

- Routine implementation choices with low impact
- Temporary decisions that will be revisited within days
- Individual code-level decisions that are covered by style guides
- Choices that are trivially reversible

## Status Lifecycle

```
Proposed  -->  Accepted  -->  Deprecated
                          -->  Superseded by ADR-NNN
```

| Status                  | Meaning                                                          |
|-------------------------|------------------------------------------------------------------|
| **Proposed**            | Under discussion, not yet decided                                |
| **Accepted**            | Decision has been agreed upon and should be followed             |
| **Deprecated**          | No longer relevant due to changes in the project or environment  |
| **Superseded by ADR-NNN** | Replaced by a newer decision; link to the replacement          |

### Rules

- An ADR is immutable once accepted; never edit the original text
- To change a decision, write a new ADR that supersedes the old one
- Update the old ADR's status to "Superseded by ADR-NNN"
- Keep deprecated and superseded ADRs in the repository for history

## Evaluating Alternatives

Use a structured comparison for every ADR with multiple options.

### Pros/Cons Matrix

```markdown
### Option A: PostgreSQL

**Pros:**
- Mature, well-understood RDBMS
- Strong ACID guarantees
- Excellent tooling ecosystem

**Cons:**
- Horizontal scaling requires additional tooling
- Schema migrations needed for changes

### Option B: MongoDB

**Pros:**
- Flexible schema for evolving data models
- Built-in horizontal scaling (sharding)

**Cons:**
- Weaker transaction support (multi-document)
- Team has limited operational experience
```

### Weighted Criteria Matrix

For complex decisions, score each option against weighted criteria:

```markdown
| Criteria              | Weight | PostgreSQL | MongoDB | DynamoDB |
|-----------------------|--------|------------|---------|----------|
| Team expertise        | 5      | 5          | 2       | 2        |
| Scalability           | 4      | 3          | 4       | 5        |
| Query flexibility     | 4      | 5          | 3       | 2        |
| Operational cost      | 3      | 3          | 3       | 4        |
| ACID compliance       | 3      | 5          | 3       | 3        |
| **Weighted Total**    |        | **80**     | **57**  | **60**   |
```

Calculation: sum of (weight x score) for each option.

## File Naming and Storage

### Conventions

| Convention       | Rule                                           | Example                              |
|------------------|-------------------------------------------------|--------------------------------------|
| Numbering        | Zero-padded 4-digit sequential                  | `0001`, `0002`, `0015`              |
| File name        | `NNNN-title-slug.md`                            | `0003-use-postgresql.md`            |
| Storage location | `docs/adr/` at the repository root              | `docs/adr/0003-use-postgresql.md`   |
| Title format     | ADR-NNN: Imperative sentence                    | ADR-003: Use PostgreSQL for storage  |

### Directory Structure

```
project-root/
  docs/
    adr/
      0001-record-architecture-decisions.md
      0002-use-typescript-for-backend.md
      0003-use-postgresql-for-primary-storage.md
      0004-adopt-rest-api-style.md
      0005-use-jwt-for-authentication.md
      README.md   (optional index)
```

### Linking ADRs to Code and Issues

- Reference the ADR in code comments near the affected area:
  ```typescript
  // See ADR-003: Use PostgreSQL for primary storage
  // docs/adr/0003-use-postgresql.md
  const db = new Pool({ connectionString: DATABASE_URL });
  ```
- Link to the relevant issue or PR in the ADR footer:
  ```markdown
  ## References
  - GitHub Issue: #142
  - Pull Request: #158
  - Related: ADR-002
  ```

## Example ADR 1: Choosing a Primary Database

```markdown
# ADR-003: Use PostgreSQL for Primary Storage

## Status

Accepted

## Context

Our application needs a primary data store for user accounts, orders,
and product inventory. We expect the following requirements:

- Strong consistency for financial transactions
- Complex queries across related entities (joins)
- Team has 5 years of collective PostgreSQL experience
- Expected scale: 10M rows in the largest table within 2 years
- Read-heavy workload with occasional write bursts

We evaluated three options: PostgreSQL, MongoDB, and DynamoDB.

## Decision

We will use PostgreSQL 16 as our primary database.

We will manage schema changes with a migration tool (golang-migrate)
and enforce that all schema changes go through reviewed migration files.

We will use connection pooling via PgBouncer for production deployments.

## Consequences

**Positive:**
- Team can be productive immediately with existing expertise
- ACID transactions simplify order and payment logic
- Rich query capabilities reduce application-level data manipulation
- Large ecosystem of monitoring and backup tools

**Negative:**
- Horizontal write scaling will require sharding or read replicas
  if we exceed expected growth significantly
- Schema migrations add friction to data model changes
- We need to manage connection pooling and tuning ourselves

**Follow-up actions:**
- Set up PgBouncer in the infrastructure configuration
- Create a migration workflow and document in the developer guide
- Establish backup and point-in-time recovery procedures
```

## Example ADR 2: API Style

```markdown
# ADR-004: Adopt REST for Public API

## Status

Accepted

## Context

We are building a public API for third-party integrations. The API
will be consumed by partners with varying levels of technical
sophistication. We need to choose between REST, GraphQL, and gRPC.

Key factors:
- Partners expect a well-documented, stable API
- Most consumers are web applications and mobile clients
- We want to minimize onboarding friction for partners
- Internal services also need to communicate, but that is a
  separate concern (see future ADR for internal RPC)

## Decision

We will adopt RESTful API design for our public-facing API.

Conventions:
- JSON request and response bodies
- Plural resource nouns in URL paths (e.g., /api/v1/orders)
- Cursor-based pagination for list endpoints
- Versioning via URL path prefix (/api/v1/, /api/v2/)
- Standard HTTP status codes per our api-design skill

We will use OpenAPI 3.1 for specification and generate
documentation from it.

## Consequences

**Positive:**
- Low learning curve for partners (REST is widely understood)
- OpenAPI tooling enables auto-generated SDKs
- Cacheable via HTTP standards (ETags, Cache-Control)
- Easy to test with curl, Postman, or any HTTP client

**Negative:**
- Over-fetching and under-fetching compared to GraphQL
- Multiple roundtrips for complex data needs
- Versioning requires maintaining parallel implementations

**Follow-up actions:**
- Create the OpenAPI specification file
- Set up API documentation generation pipeline
- Define the error response format (see api-design skill)
```

## Example ADR 3: Authentication Strategy

```markdown
# ADR-005: Use JWT with Short-Lived Access Tokens for Authentication

## Status

Accepted

## Context

We need to authenticate users and authorize API requests. The
application has both a web frontend and mobile clients. Requirements:

- Stateless authentication to simplify horizontal scaling
- Support for token refresh without full re-authentication
- Revocation capability for compromised tokens
- Compatibility with OAuth2 for future third-party integrations

Options evaluated:
1. Session-based authentication with server-side storage
2. JWT with long-lived tokens
3. JWT with short-lived access tokens and refresh tokens

## Decision

We will use JWT-based authentication with:

- **Access tokens:** 15-minute expiry, signed with RS256
- **Refresh tokens:** 7-day expiry, stored in the database, rotated
  on each use (refresh token rotation)
- **Token storage:** Access token in memory (frontend), refresh token
  in httpOnly secure cookie
- **Revocation:** Refresh tokens can be revoked by deleting from the
  database; access tokens are short-lived enough to not require
  explicit revocation in most cases
- **Key rotation:** RSA key pairs rotated quarterly with JWKS endpoint

## Consequences

**Positive:**
- Stateless verification of access tokens (no database lookup per request)
- Refresh token rotation limits the window for stolen tokens
- RS256 allows verification without sharing the signing key
- JWKS endpoint enables key rotation without downtime

**Negative:**
- Cannot instantly revoke access tokens (15-minute window)
  - Mitigation: for critical actions (password change, detected breach),
    maintain a short-lived deny list checked by middleware
- Refresh token storage adds database dependency
- Token handling complexity on the client side
- Key rotation process needs careful implementation

**Follow-up actions:**
- Implement the JWKS endpoint
- Create middleware for token verification
- Document the token refresh flow for frontend and mobile teams
- Set up monitoring for failed authentication attempts
```

## ADR Review Checklist

Before accepting an ADR, verify:

- [ ] Context explains the problem clearly enough that someone new can understand it
- [ ] All viable alternatives are listed and evaluated
- [ ] The decision is stated explicitly and unambiguously
- [ ] Both positive and negative consequences are acknowledged
- [ ] Follow-up actions are identified
- [ ] The ADR is linked to relevant issues or PRs
- [ ] The file follows naming conventions (NNNN-title-slug.md)
- [ ] Status is set to "Proposed" for review, "Accepted" after approval
- [ ] At least two team members have reviewed the ADR

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/claude-code-community-ireland) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-13 -->

