ADRs for platform teams: how infrastructure decisions become constraints for product teams

Platform teams make decisions that create hard constraints for dozens of product teams who weren't in the room. Standard ADR templates were designed for the team that made the decision — they assume shared context, a known audience, and readers who were at least briefed on why the decision was made. Platform ADRs are written by one team and read by others who discover the decision only when it constrains something they're trying to build. The template that works for a product team ADR is the wrong template for a platform team ADR.

The failure mode is specific: a platform team writes a solid ADR for their own records — context, alternatives considered, rationale, consequences. The document satisfies the standard checklist. Twelve months later, a product engineer on a service team encounters a deployment failure related to a Kafka topic naming convention. They search the decision archive. They find the ADR. It explains why the platform team chose Kafka over RabbitMQ in reasonable detail. It does not explain what the naming convention is, which services it applies to, whether theirs is one of them, or who to talk to if it creates a problem. The engineer closes the ADR knowing why the platform team chose Kafka. They still don't know what to do about their deployment failure.

This is not a failure of ADR quality in the conventional sense. The record is accurate; the rationale is clear; the decision is documented. It's a failure of audience modeling: the platform team wrote an ADR for the readers who were present for the decision, not for the readers who will encounter the decision as a constraint years later. These are different readers with different questions, and they need different documents.

The audience asymmetry

A product team ADR is written by and for the same team. The readers were present for the decision, or were briefed on it, or at least have access to the teammates who made it. The ADR is primarily a record for that team's own use — a durable reminder of the reasoning, the alternatives, and the tradeoffs, available when the next engineer joins or the decision is challenged six months from now. The context in the ADR is supplementary to the shared context the team already has.

A platform ADR is written by one team and read by product teams who encounter the platform decision as a constraint on their own work. The trigger for reading a platform ADR is almost never intellectual curiosity about the platform team's reasoning. It is frustration: why can't we do X? Why do we have to use Y? Why does this service have this dependency? The reader arrives at the ADR wanting to know: what is the constraint precisely, does it apply to us, who decided this, and can we appeal? The platform ADR is doing a job that product team ADRs never have to do: explaining a constraint to someone who had no input on it and may not agree with it.

This asymmetry has a straightforward implication. Standard ADR guidance focuses on documenting the decision for the team that made it. Platform ADRs need to document the decision for the teams that live with it — and those teams have different information needs. The overlap is real: both audiences benefit from clear rationale and honest consequences. The gap is in four sections that standard templates rarely include.

Blast radius: which teams does this constrain?

The blast radius section answers the question product engineers ask first: does this apply to us? Standard ADR templates don't include it because it's rarely necessary for a product team ADR — the team writing the record is the team the record constrains. For platform ADRs, the blast radius section is the most-read part of the document after the title.

The blast radius has two halves: scope and exclusions. Scope names the teams, services, or domains that the platform decision constrains. "All services that publish or consume domain events must use the platform Kafka cluster." Exclusions name what the constraint explicitly does not cover. "This does not apply to batch ETL pipelines that process data exclusively within the analytics domain, or to inter-service RPC calls via gRPC." Without explicit exclusions, teams either over-apply the constraint (treating it as applying to everything) or under-apply it (assuming it doesn't apply to them). Both failure modes are common, and both are avoidable if the platform ADR names the intended scope precisely at the time the decision is made — when the platform team has the most context about which teams and use cases they were designing for.

The blast radius section also creates accountability. When a product team's service is in the named scope, they know they need to comply. When a service is out of scope, they know they're working without a safety net from the platform — any similarity to the platform's pattern is coincidence, not guarantee. The explicitness is valuable even when it makes the platform team's work harder: "we don't know yet which services this applies to" is an honest blast radius statement for an early decision, and it at least surfaces the uncertainty rather than leaving product teams to guess.

Interface contract: what does compliance actually look like?

The interface contract section is where most platform ADRs have the largest gap. "Chose Kafka over RabbitMQ for the event bus" is a decision statement. It is not an interface contract. A product engineer reading this ADR knows the platform team uses Kafka. They do not know what they need to do in order to use it correctly.

An interface contract for the same decision would say: the platform provides a Kafka cluster at bootstrap address X. Topics are provisioned by filing a PR against the platform-config repository using the schema defined in TOPIC_TEMPLATE.md. Consumer group naming follows the pattern service-name/consumer-purpose where service-name matches the entry in the service registry. The platform team is responsible for cluster availability, topic provisioning (SLA: one business day), and Kafka version upgrades with two weeks notice. Product teams are responsible for: schema compatibility (no breaking changes without a new topic version), consumer group lifecycle (the platform does not clean up stale consumer groups), and retry logic (the platform provides no built-in dead letter queue; teams implement their own or request one via the topic provisioning process).

The difference between these two representations is not documentation thoroughness — it is the difference between a decision record and a compliance guide. Platform ADRs need to be both. The decision record section explains why the platform team made the choice. The interface contract section explains what product teams do with that choice. Most platform ADRs contain only the first part.

The Nygard ADR template's Consequences section is the natural home for interface contract content, but the section as standardly used describes what the decision-making team lives with — not what other teams must comply with. Extending the Consequences section to include "Consequences for consuming teams" as a named subsection is one approach. A standalone "Interface Contract" section is cleaner for complex platform decisions with many affected teams.

The constraint propagation problem

When a platform ADR lacks a blast radius section and an interface contract, product teams infer both from the behavior of the platform service and from each other. This inference chain is the constraint propagation problem, and it compounds over time in ways that make later changes unexpectedly expensive.

The pattern: the platform team decides Kafka for event infrastructure, documents the choice, and ships the cluster. Product team A onboards first. They observe that existing topics use a naming pattern that looks like domain.entity.action. This pattern isn't documented anywhere — it was an organic choice by whoever first created topics. Team A follows the pattern. Product team B onboards later and observes topics from teams A and C. They conclude that domain.entity.action is the convention and follow it. Over two years, this undocumented convention propagates across fourteen services. When the platform team wants to introduce topic namespacing by environment (adding a prod. or staging. prefix), they discover that the naming assumption has propagated so deeply that the migration would touch fourteen services simultaneously, with no documentation of where the assumption was made or whether it is truly required by any of them.

The blast radius of the original Kafka decision, documented at decision time, would have included the naming convention as part of the interface contract. Teams onboarding later would have read the contract, not inferred it from neighbors. The migration would still be work, but the blast radius would be knowable — the platform team would know which services to coordinate with rather than discovering the scope through archaeology.

Post-mortems often surface this pattern — the incident that revealed a propagated constraint that nobody knew was load-bearing. A constraint that was implicit in the platform decision accumulated through inference across several services, and its full extent was unknown until something broke. Writing the interface contract at decision time converts implicit constraints into explicit ones before the inference chain forms.

Consulted vs. informed: the legitimacy record

The consultation record is the section that platform teams are most likely to omit because it requires the most uncomfortable honesty. Recording which teams were consulted (had meaningful input on the decision) versus which were informed (notified of the outcome after the decision was made) is the political legitimacy signal for the constraint.

These are different statements: "We chose Kafka for the event bus after consulting teams A, B, and C; teams D, E, and F were informed after the decision was finalized." The second statement creates a record that determines the legitimacy of appeals. A product engineer whose team was in the consulted group and who disagrees with the decision is disagreeing with a constraint that their team had input on; their appeal requires new evidence or a changed context, not just a preference. A product engineer whose team was in the informed group and who disagrees has a legitimate argument that their use case was not considered; the platform team should hear their input, even if the decision ultimately stands.

Without this record, all constraints look the same regardless of how they were made. Teams that were consulted and teams that were informed are indistinguishable from the perspective of the constraint. This creates two pathways to organizational dysfunction: teams that were consulted and disagree escalate needlessly, as if they had no voice; teams that were informed but have a real objection have no documented basis for re-opening the conversation, so they either comply silently or raise the issue to the wrong level. The consultation record eliminates both: it makes the process transparent, it names the teams with standing to object, and it gives the platform team a defensible position when a constraint is challenged.

The decisions that never get written down often include the organizational context — who was in the room, who wasn't, why certain teams weren't consulted. This context evaporates fast. The platform architect who remembers which teams had input will rotate, change roles, or forget within a year. The consultation record is the only durable version of this context.

The revisitation condition

Every platform constraint should have a named condition under which the platform team is explicitly open to revisiting it. Without this, constraints appear permanent, and product teams who disagree have no legitimate path except escalation or quiet non-compliance.

A revisitation condition for the Kafka decision might be: "This constraint will be revisited if: (a) a product team demonstrates a use case that Kafka cannot satisfy within reasonable operational overhead, (b) the platform team evaluates a successor technology after Kafka reaches end-of-life in the factory's standard support window, or (c) organizational growth changes the operational model to the point where a managed event service becomes cost-comparable to operating the cluster." None of these conditions is an invitation for product teams to immediately lobby for RabbitMQ. They are an explicit acknowledgment that the constraint is not unconditional, and a named set of circumstances under which re-evaluation is legitimate.

The revisitation condition also prevents the common failure mode of constraints that outlast their rationale. A platform decision that was correct for a team of fifteen engineers at a particular funding stage may be wrong for a team of eighty at a different infrastructure budget. Without a revisitation condition, the constraint accumulates inertia — it becomes harder to challenge because there is no mechanism for challenging it, not because it remains correct. A named revisitation trigger makes it possible to re-evaluate without implying that the original decision was wrong.

The temporal mismatch

Platform ADRs are written when the platform team has the most context about the decision. They are read when product engineers have the least context and the highest frustration. This temporal mismatch is the root cause of most platform ADR failures.

At decision time, the platform architect knows: which product teams' use cases drove the requirements, what tradeoffs were made on behalf of teams who weren't present, which escape hatches were considered and rejected, which edge cases are known and accepted. This knowledge is available at decision time and degrades steadily afterward — the architect will rotate, the deliberation sessions will fade, and the organizational context that made the decision legible will scatter across Slack threads, stale meeting notes, and memories of engineers who have since left.

The new CTO inheriting a platform faces this problem at maximum intensity: they discover constraints without context, enforce them without understanding their scope, and make new decisions that conflict with implicit constraints that were never documented. The platform ADR with blast radius, interface contract, and consultation record is the document that makes this inheritance tractable — not because it captures everything, but because it captures the parts that decay fastest.

The temporal mismatch also explains why platform ADRs should be written before the platform service is deployed, not after. After deployment, the blast radius is harder to articulate because product teams have already started making assumptions about it. The interface contract is harder to write because the informal conventions that teams have adopted may already diverge from what the platform team intended. The consultation record is impossible to reconstruct accurately. The window for writing a complete platform ADR is at decision time or immediately after — it shrinks with every team that onboards without one.

Writing the platform ADR in practice

The practical approach is to extend a standard ADR template with four sections. The Nygard format works as a base; the additions slot naturally alongside or within the existing sections.

Blast Radius follows the Decision section and has two parts: Scope ("this constraint applies to all services that...") and Exclusions ("this does not apply to..."). Write both. Uncertain scope should be stated as uncertain: "At decision time, we believe this applies to [teams A, B, C]; we have not evaluated [domains D, E] and teams in those domains should consult the platform team before assuming this constraint applies or does not apply to them."

Interface Contract follows or replaces the standard Consequences section for platform-level detail. It names what the platform provides, what product teams are responsible for, and where the boundary lies. This section should be written as if it will be read by an engineer who is onboarding to the platform service for the first time — because that is who will read it most often, and that is when getting it right matters most. The Consequences section in the standard Nygard format can cover the platform team's own consequences ("we now own a Kafka cluster, which requires..."); the Interface Contract section covers the consequences for product teams.

Consulted Teams / Informed Teams is a brief table or list. Consulted: teams who had input before the decision was finalized. Informed: teams who were notified after. Include dates if the consultation was substantive. This section does not need to be long — three to five names per category is typical for most platform decisions.

Revisitation Condition names two to four named trigger conditions under which the platform team will re-evaluate the decision. These should be honest: if the platform team would genuinely re-evaluate the decision given evidence X, name that evidence. If certain conditions would not trigger a re-evaluation regardless of product team preferences, it is honest to say so.

These four additions don't change the core ADR practice. They extend it for an audience the standard template wasn't designed for. The title still follows the decision-statement format — "Chose Kafka over RabbitMQ for domain event infrastructure" — and the body still contains the alternatives evaluated and the rationale. The additions make the record usable by the teams who will read it under constraint rather than under collaborative context.

The AI chat extraction advantage for platform decisions

Platform architects make consequential decisions in AI chat, often across multiple sessions and over several weeks. The deliberation session contains what the post-hoc summary omits: which product teams' use cases were explicitly designed for, what tradeoffs were made on behalf of teams who weren't present, which escape hatches were considered and rejected, what the constraint was expected to cost each affected team.

A platform ADR written from the extracted deliberation session is more complete than one written from memory, for a specific reason: the organizational context — which teams were explicitly considered, what their use cases drove the requirements — is the first category of information lost from memory. The architect who writes the platform ADR three weeks after the decision remembers the technical rationale clearly and the organizational context poorly. The extraction produces a record where the technical rationale and the organizational context are both present, because both were present in the deliberation.

The blast radius section in particular benefits from extraction. The original deliberation often names specific services and teams that influenced the decision — "the real-time analytics service has a latency requirement that ruled out SQS" — and these references are the raw material for the blast radius section. Without the extraction, this context is available only to the architect who remembers it, and it decays. With the extraction, it is in the record and available to the product engineer reading the ADR two years later to understand whether their service is in scope.

The ADR as a forcing function is especially true for platform decisions: writing the blast radius section changes the decision. A platform architect who writes "this constraint applies to all 23 services that publish or consume events" before the decision is finalized has a different view of the decision's scope than one who writes it afterward. The act of naming the blast radius at decision time surfaces whether the platform team has actually consulted the 23 teams whose services will be constrained, or whether the constraint is being applied by assumption.

What the record looks like when it works

A platform ADR that includes all four additions answers the four questions a product engineer asks when they encounter a platform constraint: what is the constraint precisely (Interface Contract), does it apply to us (Blast Radius), who decided this (Consulted/Informed), and can we appeal (Revisitation Condition). The record does not need to be long to answer these questions — a well-written platform ADR with these four sections added is 600-900 words, not a manifesto.

The downstream effect is that the ADR archive contains records that product teams actually use, rather than records that product teams ignore and infer constraints from behavior instead. When an engineer onboards to a service and discovers a Kafka dependency, they read the platform ADR and understand the naming convention, the provisioning process, and who to contact — not because the ADR is thorough documentation of everything about Kafka, but because it answered the specific questions that matter to a new reader encountering the constraint for the first time.

The signal that a platform ADR is working is not that it gets cited in review comments or referenced in architecture discussions — though both are good signs. The signal is that onboarding engineers stop asking the platform team the same four questions repeatedly, because the answers are already in the record. The platform team's time is freed for decisions, not archaeology. The product teams' time is freed for building, not for inferring constraints from the behavior of neighboring services. That is the cost that an undocumented platform constraint accumulates over its lifetime, and it is the cost that a well-written platform ADR prevents.

Further reading