DaC at the platform/product boundary: who owns which decisions
The platform owns the foundation decisions. The product owns the business decisions. Most of the tug-of-war I've watched between platform and product teams comes down to no one having drawn that line in writing. DaC draws it, by making the decision surface itself the contract between them.
Here's the fight I've watched play out, in some form, at every enterprise that has both a platform team and a product team. The product team wants to ship a workflow change, bumping an approval threshold, adding a new feature gate, tweaking the steps in the agentic pipeline that handles refunds, and they file a ticket because they don't have access to the thing that controls it. The platform team picks up the ticket and says "that's a product decision, you should be able to do that yourself." The product team says "I tried; the form rejected it; the runbook says it needs a platform team review." Round and round.
Or the inverse. The product team ships something they shouldn't have, flipped a flag that controlled the isolation guarantee between two tenants, because the flag was on the same form as the workflow tweaks, and now the platform team is in incident response figuring out how a product config change leaked across a tenant boundary.
Both fights have the same root cause: nobody drew the line. Both teams are editing the same surface, and the surface doesn't know which decisions belong to whom. Decisions as Code only works when that line is drawn plainly, and the decision surface itself is the place where the line lives. The surface is the contract. The contract is what prevents the tug-of-war.
This piece is about where that line goes in practice, what sits with the platform, what sits with the product, and the pattern that lets both sides ship without stepping on each other.
The two kinds of decisions
The simplest framing I have: there are foundation decisions and there are business decisions. Foundation decisions are about how the platform itself behaves, what guarantees it makes, what the underlying contracts are, what happens when something goes wrong. Business decisions are about what the product does on top of those guarantees, which workflows run, which steps they include, which thresholds gate what behavior.
The platform team owns the foundation decisions because that's their job. They're accountable when an isolation guarantee leaks, when an audit trail goes missing, when a versioning policy lets a breaking change through. None of those failure modes are things a product team can be on the hook for, the product team didn't pick the foundation, doesn't operate it, doesn't have the context to evaluate the trade-offs.
The product team owns the business decisions because that's their job. They're accountable when the refund workflow approves things it shouldn't, when a feature gate lets the wrong cohort in, when an approval threshold was set too low and the company ate a fraud loss. None of those are things a platform team can be on the hook for, the platform team doesn't know the business policy and doesn't get paged when the conversion funnel breaks.
Sounds obvious stated this way. In practice the boundary gets blurry, because both kinds of decisions end up on the same surface (the same form, the same YAML file, the same Backstage template) and the form doesn't tell you which fields are which. When something goes wrong, both teams are in the room, and neither one is sure whose decision failed.
What sits with the platform
Here are the kinds of decisions that, in every system I've designed, end up on the platform team's side of the line.
Versioning policy. What happens when a model version is bumped, an API contract changes, a workflow definition is updated. Whether old versions stay reachable. How long. Whether consumers are pinned by default or float to latest. Foundation behavior over time, if product teams make this per-workflow the resulting fragmentation is untenable.
Isolation guarantees. What "tenant" means. Where the boundary is enforced. What can cross it. Whether it's namespace-level, network-level, identity-level, or all three. A product team should never be in a position to weaken an isolation guarantee by checking a box, because they don't have the threat model to evaluate the cost.
Audit retention. How long audit events live, where they're stored, who can read them, whether they're cryptographically signed. The product team has opinions about what should be audited (a business decision) but retention, storage, and integrity are foundation concerns. Per-workflow adjustments turn the platform's compliance posture into a patchwork.
Resource and sizing classes. What "small," "medium," "large" mean in CPU, memory, GPU, storage terms. Product picks a class; platform defines what the class means.
Security defaults: network policies, identity attached to workload class, admission controls, allowed images. All foundation.
Observability primitives. Which metrics are emitted, which traces are sampled, where logs land, what the standard label set is. Product consumes; platform produces.
These are the decisions that, if a product team makes them ad hoc and per-workflow, you end up with the eighty-nine-row YAML and a platform that's leaking. They belong below the surface, owned by templates and defaults the platform team controls.
What sits with the product
Now the other side.
Workflow steps. What the agentic pipeline does. Which tools it calls, in what order, with what guardrails. Platform provides the framework; product writes the workflow. The platform shouldn't have an opinion on whether the refund pipeline calls the fraud-check service before or after the inventory check.
Approval thresholds: where the human-in-the-loop kicks in, above what dollar amount, for what risk class, with what escalation path. Business decisions that depend on the company's risk appetite and the product's economics. Platform provides the machinery; the threshold is the product's call.
Feature gates. Which cohorts see which features. When a feature graduates from beta to GA. Platform provides the gating foundation; product decides who's in which bucket.
Eval thresholds. What "good enough" means for a model serving the recommendations endpoint. What accuracy. What latency budget. What hallucination rate is tolerable. Platform provides the eval pipeline; product defines the bar.
Model selection. Which model the application uses, within the catalog of approved models. Platform decides which models are approved (a foundation decision about supply-chain trust, cost, operational support); product picks among the approved set.
Cost-center and ownership labels. Who pays. Who's accountable. Who's on call. Platform consumes these; product is the source of truth.
If the platform team tries to make these decisions centrally, you get a platform that doesn't fit any specific product's needs and gets routed around. Every product team would set the threshold differently because every product should.
The surface is the contract
The pattern that prevents the tug-of-war: the decision surface itself becomes the plain contract between the two teams.
What that looks like, concretely. There is a defined set of fields on the surface, and every field has an owner. The "workflow steps" field is owned by the product team. The "audit retention" field is owned by the platform team, and is not on the product team's surface at all. It lives in the standards repo, with a default the platform team controls, surfaced to the product team as a read-only attribute they can see ("this workflow class retains audit events for 7 years") but cannot edit.
The platform team's contract obligation: keep the foundation decisions stable and visible. Don't change audit retention behavior under the product team without telling them. Don't tighten an isolation guarantee in a way that breaks running workflows without a migration path. The foundation is theirs to evolve, but the evolution is a contract change, communicated plainly.
The product team's contract obligation: make the business decisions on the surface that's been curated for them, and don't try to route around it. If the surface doesn't have the field they need, they file a request to add it, they don't reach into the platform's foundation and start poking at the underlying primitives. The surface is a contract; routing around it is a contract violation.
This is the only pattern I've seen survive the inevitable moment when something goes wrong. When the audit fails, the platform team owns the response, because audit retention was on their side of the line. When the refund workflow approves something it shouldn't have, the product team owns the response. The line is in the surface. Nobody has to argue.
Where it gets hard
The genuinely hard cases sit on the boundary itself. Whether tenant isolation should be loosened for a multi-tenant combination feature is both a foundation decision (it changes the platform's guarantees) and a business decision (it serves a real product use case). Whether a new model class needs a separate eval pipeline is both a foundation decision (the platform team commits to maintain it) and a business decision (the product team has the use case).
The way I've handled these in practice: make them explicit decisions made jointly, with both teams in the room, and the outcome captured in the standards repo as a new platform-side field that the product surface can then reference. The decision moves from the boundary to one side of the line, but the move is deliberate, not something one team does unilaterally and the other finds out about during incident review.
Here's how I think about it, borrowed from how I think about where DaC sits in the broader stack: if the decision changes the platform's guarantees, it goes to the platform side and lives in the standards repo. If the decision changes the product's behavior within those guarantees, it stays on the product surface. Most decisions sort cleanly; the genuinely ambiguous ones get the joint-conversation treatment. The conversation is cheaper than the tug-of-war.
What I tell teams
When I sit down with a platform team and a product team that have been having this fight for months, the conversation is short. Take the current self-service surface. For every field, ask two questions. Is this a decision the product team would make differently across different workflows? If yes, it's product-owned. If no, if every workflow on the platform should have the same value or pick from the same small set, it's platform-owned and shouldn't be on the surface at all. Is the consequence of getting it wrong a foundation-level failure or a business-level failure? Foundation-level failure means platform-owned. Business-level failure means product-owned.
Two questions. They sort almost every field. The ones that resist sorting are the genuinely ambiguous boundary cases, worth a joint conversation about, because the disagreement is the data.
The end state: a surface where the product team makes their decisions and ships, and the platform team makes theirs and the surface picks them up. Nobody is filing tickets across the boundary, because the boundary is no longer a queue. It's a contract.
Same pattern I've been using since the OneFuse days (the Property Toolkit lineage), in different costumes. The foundation rotates. The boundary problem is constant. DaC is what makes it tractable.
, Sid