Technical Decision Records

Document architectural decisions using Architecture Decision Records (ADRs) to preserve context, enable future teams to understand why decisions were made, and prevent repeated debates about settled questions.

Technical Decision Records (TDRs) are lightweight, persistent documents that capture the reasoning, trade-offs, and outcomes of significant engineering decisions. They matter most when a team must align on a major architectural or operational choice—such as adopting a new database, redesigning a service’s API contract, or choosing a CI/CD platform—and when the decision must survive changes in team membership, product direction, or technology landscape. A TDR is not a meeting minutes document, nor a project proposal. It is a decision artifact that answers *why* a choice was made, *what* alternatives were considered, and *how* the team arrived at the final conclusion.

When to Write a TDR

A TDR should be initiated whenever a decision has significant technical impact, spans multiple teams, requires substantial investment, or involves non-obvious trade-offs. The trigger is a decision that cannot be reversed easily, such as:

The TDR should be written *before* implementation begins, ideally as part of the design phase. It should be authored by the lead engineer or tech lead, reviewed by peers, and approved by an Architecture Review Board (ARB) or equivalent governance body.

How to Structure a TDR

A TDR follows a standard structure, using only universally applicable tools and patterns. The document is a single Markdown file, stored in a version-controlled repository (e.g., docs/decisions/ in a Git repository), and versioned using Git commits and branches.

Core Sections

Each TDR must include:

This structure is enforced via a template file, templates/decision.md, which includes frontmatter for metadata:

---
title: Choose Kafka for event streaming
status: implemented
author: [email protected]
created: 2024-03-15
updated: 2024-04-02
related: 
  - /docs/architecture/microservices.md
  - /docs/pipeline/monitoring.md
  - https://github.com/org/project/pull/217
---

The status field is updated with a simple Git commit:

git commit -m "TDR: implemented - Choose Kafka for event streaming"
git push origin main

Writing the Decision

When drafting a TDR, the writer must focus on clarity and depth, avoiding surface-level summaries.

Crafting the Context

The context section explains *why* the decision is needed. It answers: What problem does this solve? Who is affected? What are the current pain points?

Example: > Our current messaging stack uses RabbitMQ for internal service communication. As our user base grows, we observe message delays during peak traffic, and consumers frequently fall behind. The current setup lacks replayability, and there is no centralized event log. We need a system that supports high-throughput, durable event streaming with replayability and horizontal scalability.

Evaluating Alternatives

For each alternative, include a pros/cons table with at least three criteria: throughput, durability, complexity, scalability, and developer experience.

| Option       | Throughput | Durability | Complexity | Scalability | Developer Experience |
|--------------|------------|------------|------------|-------------|----------------------|
| Kafka        | High       | High       | Medium     | High        | Good                 |
| Pulsar       | Very High  | Very High  | High       | Very High   | Excellent            |
| RabbitMQ     | Medium     | Medium     | Low        | Medium      | Excellent            |
| AWS SQS      | Low        | Medium     | Low        | Medium      | Good                 |

Each alternative must be described with a short paragraph, including real-world constraints:

Building Rationale

The rationale is the heart of the TDR. It must explain *why* the selected option is best, supported by evidence, trade-offs, and real constraints.

Example rationale:

> We chose Kafka for event streaming because it offers the best balance of throughput, durability, and scalability. Kafka’s log-based architecture enables efficient message replay and consumer offset management. Its built-in replication and partitioning allow horizontal scaling across thousands of messages per second. While Pulsar offers superior performance and features, it introduces significant complexity in deployment and operations. RabbitMQ is simpler but does not scale well beyond medium workloads. SQS is cost-effective but lacks ordering guarantees and long-term retention. Given that we expect to process 100K events per second with 30-day retention and need to replay events for analytics, Kafka’s design directly addresses these requirements.

The rationale must include:

Reviewing a TDR

A TDR is not final until it has been reviewed by peers and stakeholders.

Review Process

The review is conducted via pull request in Git. The reviewer uses a standard checklist:

Reviewers comment directly on the Markdown file using GitHub-style comments or a lightweight review tool like pr-review or git review.

Common Review Pitfalls

Approving and Merging

Once reviewed, the TDR is approved and merged. The status field is updated to approved or implemented. The final decision is documented in the CONTRIBUTING.md file, and a decision badge is added to the project’s README.

![TDR: Implemented](https://img.shields.io/badge/decision-implemented-green)

Maintaining TDRs Over Time

TDRs are not static. They evolve as the system changes.

Versioning and Updates

Each TDR is versioned in the repository. When a decision is revised, a new version is created with a change log:

## 2024-05-10: Update Kafka configuration strategy

- Added configuration for `log.message.timestamp.type` to `CreateTime`
- Changed `replica.fetch.max.bytes` from 1MB to 4MB
- Added `retention.ms` for 30 days
- Removed `message.timestamp.difference.max.ms`

Updated rationale to reflect new retention strategy.

The status is updated to implemented, and a new updated date is set.

Tracking Decision Lifecycle

A central decisions/index.md file lists all TDRs, sorted by creation date:



## 2024-03-15: Choose Kafka for event streaming
- Status: implemented
- Author: [email protected]
- Related: /docs/architecture/microservices.md

## 2024-02-28: Adopt OpenTelemetry for observability
- Status: approved
- Author: [email protected]
- Related: /docs/observability/tracing.md

## 2024-01-10: Migrate database from MySQL to PostgreSQL
- Status: proposed
- Author: [email protected]

This index is updated automatically using a scripts/generate-decisions-index.sh script:

#!/bin/bash
echo "# Technical Decision Records" > docs/decisions/index.md
echo "" >> docs/decisions/index.md
echo "## $(date +%Y-%m-%d)" >> docs/decisions/index.md

find docs/decisions -name "*.md" -not -name "index.md" | sort | while read file; do
  title=$(grep "^title:" "$file" | head -1 | cut -d: -f2- | sed 's/^ *//')
  status=$(grep "^status:" "$file" | head -1 | cut -d: -f2- | sed 's/^ *//')
  author=$(grep "^author:" "$file" | head -1 | cut -d: -f2- | sed 's/^ *//')
  echo "## $(basename "$file" .md): $title" >> docs/decisions/index.md
  echo "- Status: $status" >> docs/decisions/index.md
  echo "- Author: $author" >> docs/decisions/index.md
done

Failure Modes and Sharp Edges

Silent Failures

Confused Options

Production Lessons

Tools and Workflow

The entire TDR process is built on standard, widely available tools:

A TDR is not tied to a specific platform. It is a pattern that works in any engineering organization, regardless of stack or tooling.

Summary

A Technical Decision Record is not a document. It is a practice. It is the process of capturing, reviewing, and maintaining decisions that shape the technical trajectory of a system. It ensures that no decision is lost to time, that trade-offs are visible, and that teams can learn from past choices. When done well, a TDR becomes a living artifact—trusted, discoverable, and indispensable.

This page was rewritten on 17 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.