Architecture Decision Records: Tracking Every Critical Technical Choice with ADRs
TL;DR
Architecture Decision Records: Tracking Every Critical Technical Choice with ADRs
“Series: S2 Architecture Overview · Article 15 | Level: Intermediate | Reading Time: 18 min
TL;DR
- Architecture Decision Records (ADRs) are a lightweight documentation method for recording "why a particular technical decision was made." coomia-dip uses ADRs to systematically track every critical decision, from communication protocol selection (gRPC vs REST) to build tool selection (Gradle vs Maven).
- A good ADR does not just document "what was chosen" -- more importantly, it documents "why other options were not chosen." Rejected alternatives and their rationale are crucial for future developers understanding the architectural context -- they answer the most commonly asked question: "why didn't we use X back then?"
- ADRs are "living documents," not "historical archives." When changes in the technical landscape require modifying an original decision, the old ADR is not deleted but rather superseded by a new ADR that references it. This preserves the complete decision evolution chain.
#1. Introduction: The Forgotten "Why"
#1.1 The Question Every Project Faces
Throughout a software project's lifecycle, the most frequently asked question is not "how is this implemented?" (the code answers that), but "why was it implemented this way?"
"Why use gRPC instead of REST for internal communication?"
"Why use Gradle instead of Maven for Java projects?"
"Why use Python instead of Java for Reasoning & Decision Layer?"
"Why use Kafka instead of RabbitMQ?"
"Why use Doris instead of ClickHouse?"
These questions are raised weekly by newly onboarded developers in the coomia-dip project. Without systematic documentation, the answer typically relies on "finding the person who was involved in the decision" -- and when that person leaves the team, this invaluable architectural context is lost forever.
#1.2 What Is an ADR
An ADR (Architecture Decision Record) is a lightweight, structured document format for recording significant architectural decisions. Each ADR contains:
- Context: The situation and constraints faced when making the decision
- Decision: What was ultimately chosen
- Alternatives: Options considered but not selected, with rationale
- Consequences: Positive and negative impacts of the decision
An ADR is not a design document, not a technical specification, not meeting minutes -- it is a distilled decision record, typically completable in 1-2 pages.
#1.3 coomia-dip ADR Practice
The coomia-dip project uses ADRs as one of its core architectural governance tools. In the project's CLAUDE.md, multiple technical red lines are effectively the enforcement results of key ADRs:
No REST/JSON between internal services (must use gRPC) → ADR-001
No Spring Boot for Reasoning & Decision Layer + Agent Runtime Layer (must use Python) → ADR-003
No Maven for Java projects (must use Gradle) → ADR-005
No bypassing Ontology for direct DB access → ADR-007
Behind each red line is a complete ADR explaining the context, rationale, and trade-offs.
#2. ADR Template and Format
#2.1 coomia-dip ADR Template
coomia-dip uses the following standardized template:
# ADR-{number}: {Decision Title}
## Status
{Proposed | Accepted | Deprecated | Superseded by ADR-XXX}
## Date
YYYY-MM-DD
## Context
{Describe the situation, constraints, and requirements at decision time}
## Decision
{Clearly state the decision made}
## Alternatives
### Option A: {Name}
- Pros: ...
- Cons: ...
- Reason not chosen: ...
### Option B: {Name}
- Pros: ...
- Cons: ...
- Reason not chosen: ...
## Consequences
### Positive
- ...
### Negative
- ...
### Risks and Mitigations
- Risk: ...
Mitigation: ...
## References
- {Related links, documents, discussions}
#2.2 ADR Numbering Scheme
coomia-dip ADRs are grouped by domain:
| Range | Domain | Example |
|---|---|---|
| 001-099 | Communication & Protocols | ADR-001 gRPC vs REST |
| 100-199 | Data & Storage | ADR-101 Doris vs ClickHouse |
| 200-299 | Compute & Runtime | ADR-201 Python for Reasoning & Decision Layer |
| 300-399 | Build & Engineering | ADR-301 Gradle vs Maven |
| 400-499 | Testing & Quality | ADR-401 Testcontainers |
| 500-599 | Deployment & Operations | ADR-501 Docker Compose |
| 600-699 | Security & Governance | ADR-601 Ontology Forced Routing |
| 700-799 | SDK & Developer Experience | ADR-701 Python SDK First |
#3. Core ADR Deep Dive: Communication Protocol
#3.1 ADR-001: gRPC Over REST for Internal Communication
Status: Accepted
Date: 2025-06-15
Context:
coomia-dip consists of 8 Layers, each an independent service or service group. These Layers require high-frequency, low-latency communication. The platform uses both Java (Control Layer + Data Layer) and Python (Reasoning & Decision Layer + Agent Runtime Layer), so the communication protocol must have cross-language capabilities.
Constraints to consider:
- Serialization compatibility between Java and Python
- Communication latency impact on derived property computation chains (see S2-07)
- Version management and backward compatibility of interface definitions
- Team learning costs and toolchain maturity
Decision:
All inter-service communication must use gRPC + Protobuf. REST/JSON is used only at the API gateway layer facing external users.
Alternatives:
Option A: REST + JSON
- Pros: High team familiarity, rich debugging tools (Postman, curl), directly testable in browsers
- Cons: JSON serialization/deserialization overhead is significant (4-5x slower than Protobuf); no strongly-typed interface definitions, cross-language compatibility depends on documentation rather than code; HTTP/1.1 creates one connection per request, no bidirectional streaming
- Not chosen because: In high-frequency internal call scenarios (e.g., derived property cascade computation may trigger dozens of cross-Layer calls), JSON serialization overhead goes from negligible to a significant bottleneck
Option B: REST + Protobuf
- Pros: Retains REST semantics while gaining Protobuf serialization benefits
- Cons: Non-standard combination with limited toolchain support; still constrained by HTTP/1.1 connection model; code generation tools are less mature than the gRPC ecosystem
- Not chosen because: A compromise between two worlds, lacking both REST's ecosystem advantage and gRPC's full capabilities
Option C: Apache Thrift
- Pros: Similar IDL + code generation to gRPC, excellent performance
- Cons: Less active community than gRPC; weaker streaming capabilities; poorer cloud-native ecosystem integration (Envoy, Istio) compared to gRPC
- Not chosen because: gRPC has become the de facto standard for cloud-native communication; choosing Thrift would increase future infrastructure integration costs
Consequences:
Positive:
- Cross-language interface compatibility is guaranteed by the Protobuf compiler, eliminating "documentation-code inconsistency" issues
- 4-5x serialization performance improvement, reducing communication overhead in derived property cascade computation
- Bidirectional streaming support provides native capability for real-time event pushing
- Natural integration with the Kubernetes ecosystem (gRPC health checks, load balancing)
Negative:
- Increased debugging difficulty -- gRPC uses a binary protocol, unlike JSON which can be viewed directly in a browser
- Team learning curve -- need to learn Protobuf syntax and gRPC concepts
- Toolchain requirements -- need to configure the protoc compiler and language-specific code generation plugins
Risks and Mitigations:
- Risk: Debugging difficulty impacts development efficiency Mitigation: Introduce grpcurl and gRPC reflection API for a curl-like debugging experience; configure gRPC-Web proxy for development environments
- Risk: Proto file changes cause cross-language incompatibility Mitigation: CI pipeline enforces dual-language compilation and contract tests (see S2-14)
#4. Core ADR Deep Dive: Technology Stack
#4.1 ADR-201: Python for Reasoning & Decision Layer + Agent Runtime Layer (Intelligence Layer)
Status: Accepted
Date: 2025-07-02
Context:
Reasoning & Decision Layer (Reasoning & Decision) and Agent Runtime Layer (Agent Runtime) need to handle:
- Rule engine evaluation
- Machine learning model inference
- AI Agent orchestration
- LLM API integration
The team needed to decide whether these two Layers should use Java (consistent with Control Layer + Data Layer) or Python.
Decision:
Reasoning & Decision Layer and Agent Runtime Layer must use Python 3.x + FastAPI. Spring Boot is prohibited.
Alternatives:
Option A: Java + Spring Boot
- Pros: Unified technology stack with Control Layer + Data Layer, team has extensive Java experience, excellent JVM runtime performance
- Cons: ML/AI ecosystem is far behind Python; integrating with PyTorch, Transformers, LangChain requires JNI or subprocess calls, adding complexity; virtually all new AI libraries and models provide Python SDKs first
- Not chosen because: AI/ML is the core capability of Reasoning & Decision Layer + Agent Runtime Layer -- choosing Java means perpetually "chasing" the Python ecosystem rather than "leveraging" it
Option B: Python + Django
- Pros: Django is Python's most mature web framework with powerful ORM
- Cons: Django is a synchronous framework, async support (async views) was added later and feels non-native; Django's ORM is unused in coomia-dip (data access goes through the Ontology layer); framework is too heavy with many unused features
- Not chosen because: FastAPI was designed async-first, perfectly matching the I/O-intensive nature of AI/ML workloads; Pydantic integration provides native data validation and serialization
Option C: Python + Flask
- Pros: Lightweight and flexible, gentle learning curve
- Cons: No built-in async support (requires Quart or ASGI adapter); no built-in data validation; no automatic OpenAPI documentation generation
- Not chosen because: FastAPI is comprehensively superior to Flask in async performance, type safety, and API documentation
Consequences:
Positive:
- Direct access to Python AI/ML ecosystem (PyTorch, Transformers, LangChain, etc.)
- FastAPI's async-native support perfectly matches the high-latency nature of LLM API calls
- Pydantic v2 provides runtime type validation, complementing Protobuf message formats
- Easier to recruit AI/ML engineers -- Python is the lingua franca of the field
Negative:
- Team needs to maintain two technology stacks (Java and Python) simultaneously
- Python runtime performance is inferior to JVM (impacts CPU-intensive tasks)
- Dependency management (pip/poetry) is less unified than Gradle
- Two languages mean different code styles and best practices, requiring dual standards
#4.2 ADR-301: Gradle Over Maven for Java Builds
Status: Accepted
Date: 2025-06-20
Context:
coomia-dip Java projects (Control Layer and Data Layer) need a build tool. The project CLAUDE.md has already listed this as a technical red line:
No Maven for Java projects (must use Gradle)
The technical rationale behind this red line needs to be documented.
Decision:
All Java projects must use Gradle 8.x for builds.
Alternatives:
Option A: Maven
- Pros: Industry standard, convention over configuration, most Java developers are familiar with it, excellent IDE support
- Cons: Verbose XML configuration, custom tasks require plugin authoring; weak incremental build capability -- nearly every build is a full build; slow multi-module project builds (2-3x slower than Gradle); inflexible, complex build requirements need extensive plugin configuration
- Not chosen because: coomia-dip Control Layer and Data Layer are both multi-module projects (10+ submodules), and Maven's full-build model wastes significant time during daily development
Option B: Bazel
- Pros: Open-sourced by Google, ultimate incremental builds and caching, multi-language support (unified Java + Python builds)
- Cons: Extremely steep learning curve, configuration complexity far exceeds Gradle; Java ecosystem integration is inferior to Gradle (many libraries lack Bazel build rules); team has no Bazel experience
- Not chosen because: Bazel's advantages materialize only in ultra-large-scale monorepos; coomia-dip's project scale is well served by Gradle
Consequences:
Positive:
- Incremental builds reduce daily development build times from minutes to seconds
- Kotlin DSL
build.gradle.ktsprovides type-safe build configuration - Gradle has excellent Protobuf code generation plugin support (
protobuf-gradle-plugin) - Good integration with Spring Boot and Quarkus Gradle plugins
Negative:
- Some team members need to transition from Maven to Gradle
- Gradle's flexibility sometimes leads to "a thousand ways to do the same thing"
- Gradle Wrapper version management requires additional attention
#5. Core ADR Deep Dive: Data Storage
#5.1 ADR-101: Apache Doris as OLAP Engine
Status: Accepted
Date: 2025-07-10
Context:
coomia-dip needs an OLAP engine to support:
- Large-scale analytical queries
- Materialized views (ComputationCoordinator's MATERIALIZED mode)
- Real-time data ingestion and near-real-time queries
- SQL compatibility (lower learning curve)
Decision:
Use Apache Doris as the platform's primary OLAP engine.
Alternatives:
Option A: ClickHouse
- Pros: Exceptional single-table query performance, high columnar storage compression, active community
- Cons: Poor multi-table JOIN performance (coomia-dip's relationship queries are frequent); limited materialized view functionality; weak distributed transaction support; real-time updates (UPSERT) require ReplacingMergeTree engine with brief data inconsistency windows
- Not chosen because: coomia-dip's Ontology queries frequently involve multi-table JOINs for object relationships, which is ClickHouse's weak point
Option B: Apache Druid
- Pros: Strong real-time ingestion, excellent time-series queries
- Cons: Incomplete SQL support; no standard UPDATE/DELETE; high operational complexity (multiple node types); weak materialized view capabilities
- Not chosen because: coomia-dip is not a purely time-series analytics scenario; full SQL semantics are required
Option C: StarRocks
- Pros: Architecture similar to Doris, slightly better in performance benchmarks, strong materialized views
- Cons: Commercially driven, community edition has feature limitations; domestic user community is less active than Doris; long-term direction influenced by commercial strategy
- Not chosen because: Doris as an Apache Top-Level Project has more open community governance and better long-term sustainability
Consequences:
Positive:
- MySQL-compatible SQL syntax lowers team learning costs
- Materialized view functionality directly supports ComputationCoordinator's MATERIALIZED mode
- Real-time ingestion + near-real-time queries satisfy most derived property computation needs
- Apache Foundation project status ensures open-source sustainability
Negative:
- Doris's ecosystem (connectors, tools) is less rich than ClickHouse's
- Not as performant as ClickHouse in extreme performance scenarios (but coomia-dip's query patterns are not extreme)
- Need to monitor Doris version upgrade compatibility
#6. Core ADR Deep Dive: Architecture Patterns
#6.1 ADR-601: Mandatory Ontology Routing
Status: Accepted
Date: 2025-06-25
Context:
The project CLAUDE.md technical red line:
No bypassing Ontology for direct database access
This red line requires all data access to go through OntologyRuntimeService, even though this means additional gRPC call overhead (2-5ms). The complete context of this decision needs to be documented.
Decision:
All service data reads and writes must go through OntologyRuntimeService's gRPC interface. Direct database connections from any service are prohibited.
Rationale (see S2-04 Ontology Kernel article for details):
- Unified permission checking: The Ontology layer performs permission validation on every operation; direct DB access bypasses the permission system
- Schema validation: The Ontology layer guarantees all writes conform to ObjectType-defined constraints
- Audit trail: Every operation automatically generates audit logs; direct DB access creates "untraceable" data changes
- Event publishing: Data changes automatically trigger CDC events; direct DB access causes derived properties to miss cascade updates
Rejected Alternative:
"Allow read-only direct access" -- it was proposed to allow direct DB connections for read-only scenarios to improve query performance. Rejected because:
- Read-only queries still require permission checking
- Read-only queries also need audit records
- Once a "read-only direct" exception is opened, it quickly evolves into "write-direct too"
- 2-5ms Ontology overhead is acceptable for most scenarios
#7. ADR Lifecycle Management
#7.1 ADR Status Transitions
Proposed
│
├── Team discussion & technical review
│
├── Accepted
│ │
│ ├── Environment changes / new requirements
│ │
│ └── Superseded (by ADR-XXX)
│ │
│ └── New ADR references old ADR
│
└── Rejected
│
└── Rejection reasons documented (equally valuable)
#7.2 When to Create an ADR
Not every technical decision needs an ADR. coomia-dip uses these criteria:
| Needs ADR | Does Not Need ADR |
|---|---|
| Choosing a database or message queue | Choosing a log format |
| Choosing a communication protocol | Choosing code indentation style |
| Choosing a programming language | Choosing variable naming convention |
| Defining security architecture patterns | Choosing a specific encryption algorithm |
| Changing system boundaries | Refactoring internal implementation details |
Simple rule: If someone will ask "why" about this decision in 6 months, write an ADR.
#7.3 ADR Update Policy
Once an ADR is accepted, its body should not be modified (it records the decision context "at that time"). If changes are needed, create a new ADR:
# ADR-102: Migrating from Doris to Doris + Iceberg Hybrid Architecture
## Status
Accepted (supersedes the "Doris as sole OLAP engine" portion of ADR-101)
## Context
ADR-101 chose Doris as the sole OLAP engine. After 6 months of operation,
cold data storage in Doris proved too expensive. Iceberg needs to be
introduced as a cold data storage layer...
#8. ADRs and Project Red Lines
#8.1 Red Lines = ADR Enforcement
Every technical red line in coomia-dip's CLAUDE.md corresponds to one or more ADRs:
| Technical Red Line | Corresponding ADR | Core Rationale |
|---|---|---|
| No internal REST communication | ADR-001 | Performance + cross-language type safety |
| No Spring Boot for Reasoning & Decision Layer + Agent Runtime Layer | ADR-201 | AI/ML ecosystem compatibility |
| No Maven | ADR-301 | Incremental build efficiency |
| No bypassing Ontology | ADR-601 | Permissions + audit + events |
No as any | ADR-702 | Type safety |
| No empty catch blocks | ADR-401 | Debuggability |
#8.2 Red Line Exception Process
If a developer encounters a genuinely special scenario requiring a red line exception, it must go through this process:
1. Submit a "Red Line Exception ADR"
├─ Explain why the red line must be crossed
├─ Describe the scope of impact
└─ Propose mitigation measures
2. Architecture Review
├─ At least 2 Senior reviewers
└─ Document review conclusions
3. If Approved
├─ Record the "scoped" exception in the ADR
├─ Set checkpoints (is the exception still necessary?)
└─ Notify relevant Layer owners
#9. Team Collaboration Value of ADRs
#9.1 New Member Onboarding
For developers newly joining coomia-dip, ADRs are among the most effective onboarding materials. By reading the core ADRs, new members can understand within 2-3 hours:
- Why these technologies were chosen over alternatives
- What alternatives were historically considered
- The trade-offs and compromises in each key decision
- Which constraints can be challenged and which are immovable
#9.2 Cross-Team Alignment
In coomia-dip's multi-Layer architecture, different teams own different Layers. ADRs ensure all teams stay aligned on critical technical decisions:
Control Layer team: "We want to expose a new interface via REST"
→ Check ADR-001 → Understand why gRPC is required
→ If special needs exist → Submit an exception ADR
Reasoning & Decision Layer team: "We want to rewrite performance-critical paths in Go"
→ Check ADR-201 → Understand why Python was chosen
→ If performance needs are legitimate → Submit new ADR evaluating Go adoption feasibility
#9.3 Technical Debt Management
The "negative consequences" and "risks" recorded in ADRs serve as an early warning system for technical debt. Teams can periodically review ADR predictions:
ADR-001's predicted risk: "Debugging difficulty impacts development efficiency"
→ 6-month review → Debugging pain points did materialize
→ Mitigated by introducing grpcurl + gRPC reflection
→ Recorded in ADR-001's "retrospective" section
#10. ADR Anti-Patterns
#10.1 Common Anti-Patterns
| Anti-Pattern | Description | Consequence |
|---|---|---|
| Retroactive writing | ADR written months after decision was implemented | Context is lost, alternatives incompletely recalled |
| Over-detailed | ADR becomes a 20-page design document | Nobody wants to read or write them |
| Missing alternatives | Only records "what was chosen" not "what else was considered" | Future developers cannot understand decision context |
| Non-actionable | "We should consider performance" | Not a concrete, actionable decision |
| Never revisited | ADR is filed and forgotten | Decision may be outdated but nobody knows |
| Stealth editing | Directly modifying accepted ADR body | Breaks the decision history chain |
#10.2 Qualities of a Good ADR
A high-quality ADR should enable a reader 6 months later to understand within 5 minutes:
- What problem was faced (Context)
- What was decided (Decision -- summarized in one sentence)
- Why alternatives were not chosen (Alternatives -- the most valuable section)
- What costs must be borne (Consequences -- honest about negative impacts)
#11. ADR Toolchain
#11.1 Storage and Organization
coomia-dip stores ADRs as part of the code repository:
docs/
└── adr/
├── README.md ← ADR index
├── templates/
│ └── adr-template.md ← Standard template
├── 001-grpc-over-rest.md
├── 101-doris-as-olap.md
├── 201-python-for-intelligence.md
├── 301-gradle-over-maven.md
├── 401-testing-pyramid.md
├── 501-docker-compose-deployment.md
├── 601-ontology-routing.md
└── 701-python-sdk-first.md
#11.2 ADR and Git Integration
ADR changes follow the same version control process as code:
- ADR creation and modification are submitted via PRs
- PRs require at least 2 reviewer approvals
- Post-merge, recorded via commit messages (using appropriate prefixes)
add: ADR-102 Doris + Iceberg hybrid storage architecture decision
#11.3 Automated Indexing
The CI pipeline includes an automation script that regenerates the README.md index on every ADR change:
# scripts/generate_adr_index.py
def generate_index(adr_dir: str) -> str:
"""Scan ADR directory and generate Markdown index"""
adrs = []
for path in sorted(Path(adr_dir).glob("*.md")):
if path.name in ("README.md", "adr-template.md"):
continue
title = extract_title(path)
status = extract_status(path)
date = extract_date(path)
adrs.append(f"| [{path.stem}]({path.name}) | {title} | {status} | {date} |")
header = "| ADR | Title | Status | Date |\n|-----|-------|--------|------|\n"
return header + "\n".join(adrs)
#12. ADRs and Architecture Evolution
#12.1 Decision Chain Tracking
ADRs form "decision chains" through cross-references:
ADR-001 (gRPC internal communication)
│
├── ADR-002 (Protobuf Schema management)
│ └── ADR-003 (Proto files mono-repo management)
│
└── ADR-004 (gRPC streaming for event pushing)
└── ADR-005 (Kafka as event backbone → replacing gRPC streaming)
ADR-101 (Doris as OLAP)
│
└── ADR-102 (Doris + Iceberg hybrid → supersedes part of ADR-101)
#12.2 Architecture Evolution Traceability
Through ADR chains, one can clearly see how the architecture evolved step by step:
2025-06: ADR-001 → Choose gRPC for internal communication
2025-07: ADR-004 → Consider gRPC streaming for event pushing
2025-08: ADR-005 → Discover gRPC streaming unsuitable for large-scale events, switch to Kafka
2025-09: ADR-006 → Build 7 event roles on Kafka (see S2-06)
This evolution chain answers "why Kafka is used for event pushing instead of gRPC streaming" -- because ADR-004 tried it, and ADR-005 documented why it was abandoned.
#13. Comparison with Palantir Foundry
| Dimension | Palantir Foundry | coomia-dip |
|---|---|---|
| Decision records | Internal technical memos (closed source) | ADR public documents (code repository) |
| Decision tracking | Confluence + JIRA | Git version control + Markdown |
| Technical red lines | Internal specification documents | CLAUDE.md + ADRs |
| New hire onboarding | Mentorship + internal training | ADR self-service reading + mentorship |
| Decision updates | Document update notifications | PR approval + Git history |
| Architecture governance | Architecture review committee | ADR submission + peer review |
As an open-source project, coomia-dip's ADR transparency is a core advantage. Any contributor can read the complete decision history and understand "why," not just see "what."
#14. Practical Recommendations
#14.1 Start Writing ADRs from Day One
Do not wait until the project "stabilizes" to start writing ADRs. The most valuable decisions typically occur early in the project, and early context is the most easily forgotten.
#14.2 Keep It Lightweight
An ADR should not exceed 2 pages. If it is growing too long, design documentation and decision records may be getting mixed together. ADRs only record "decisions" -- design details belong in other documents.
#14.3 Alternatives Are the Most Valuable Section
Spend more time writing "why not X" than "why Y." "Chose Y" is a visible fact in the code, but "why not X" is tacit knowledge that exists only in the decision-maker's mind.
#14.4 Review Regularly
Spend 1-2 hours each quarter reviewing existing ADRs:
- Which decisions' negative consequences have materialized?
- Which alternatives have become more attractive now?
- Which ADRs need follow-up ADRs to course-correct?
#Key Takeaways
-
The core of an ADR is not "what was chosen" but "why other options were not chosen." The code itself is the best documentation of "what was chosen," but "why" exists only in decision-makers' minds. When decision-makers leave the team, this critical context is lost forever. coomia-dip converts tacit knowledge into explicit documentation through its ADR system, ensuring every technical red line has traceable decision backing.
-
ADRs are "living documents," not "historical archives" -- old decisions are not deleted but superseded by new ones. This chain structure preserves complete decision evolution history. When someone asks "why did we switch from gRPC streaming to Kafka for event pushing," the ADR chain clearly records the complete attempt, problem, and change process.
-
Technical red lines must be backed by ADRs; otherwise it is "dictation" rather than "governance." Every technical red line in coomia-dip's
CLAUDE.mdcorresponds to an ADR that developers can read to understand "why this red line exists." If there is a legitimate reason to cross a red line, an exception ADR can be submitted for team review. This mechanism balances architectural consistency with flexibility.
“Series Retrospective: The S2 Architecture Overview series concludes here. From Article 1's Layered Architecture to Article 15's Architecture Decision Records, we have comprehensively presented coomia-dip's architectural design philosophy, technology selection rationale, and engineering practices. We hope these articles help readers understand not just "what coomia-dip is" but "why coomia-dip is the way it is."
Tags: #adr #architecture-decision-record #technical-governance #red-line #grpc #gradle #python #doris #ontology #decision-tracking #coomia-dip