The platform engineering decision record: why the internal developer platform you chose determines your team onboarding velocity and your infrastructure self-service ceiling

The internal developer platform decision is made when the engineering team hits a size at which the manual golden path stops scaling — typically fifteen to twenty engineers, when the time a new engineer spends waiting for their local environment to be configured, their AWS credentials to be provisioned, and their first service to be scaffolded from a verbal explanation becomes a measurable drain on the team. The choice is made under time pressure, with a rough understanding of what "developer platform" means in the abstract and a vague commitment to build something that makes developer experience better. The team evaluates Backstage, looks at Port.io's pricing page, considers whether a well-organized set of Terraform modules and setup scripts counts as a platform, and makes a decision in an afternoon that determines the maintenance budget and the self-service ceiling for the next three years.

The platform engineering decision record does not exist because the choice feels temporary — something that will be revisited and improved once the team has more time. What happens instead is that the platform is extended incrementally, each addition small enough to not require a rethinking of the underlying approach, until the cumulative weight of extensions, undocumented conventions, and deferred maintenance reveals that the platform has grown well past its design basis. The engineer who made the original choice has moved to a different role or left the company. The platform team's maintenance burden has grown from twenty percent to sixty percent of capacity. A new compliance requirement — VPC isolation for an enterprise deal, data residency controls for a GDPR audit — cannot be satisfied without migrating the infrastructure stack, and the migration scope is larger than it would have been if the trigger criteria for migration had been written down three years earlier and tracked against actuals.

Two things that happen when the decision is not written down

The Backstage implementation that the platform team could no longer maintain

A 45-person SaaS startup decided to build its internal developer platform with Backstage. The decision was made in a planning session where the head of engineering outlined the problem — new engineers were spending four days getting their local environment working, service ownership was unclear, and the on-call rotation was failing because nobody knew which team owned which service — and a staff engineer proposed Backstage as the solution because it had a service catalog, software templates, and a plugin ecosystem that could cover most of the needs. A four-person platform team was assembled with the mandate to build a portal that any engineer could use to discover services, create new services from templates, and understand the ownership and health of the infrastructure. The initial timeline estimate was four months; the actual first usable version shipped in six. No decision record was written. The choice felt like an implementation detail — "we're using Backstage" — not a strategic decision with consequences worth documenting.

At twelve months the platform had fifteen plugins: a Kubernetes plugin showing pod status, a GitHub plugin showing recent pull request activity, a PagerDuty plugin showing on-call rotations, a Datadog plugin for service health metrics, a Terraform Cloud plugin for infrastructure run history, a cost explorer plugin from a third-party contributor, and nine service-team-specific plugins built by product engineers who needed catalog integrations not covered by the official ecosystem. The template library had twelve service templates: TypeScript API service, Go gRPC service, Python data pipeline, React frontend, three variants of database migration runners, and five infrastructure templates for common patterns. The service catalog had 127 registered services. Getting a new engineer productive using the platform took approximately one day — down from four and a half days before the platform launched.

The breakdown started eighteen months in, when the four-person platform team was reduced to two through a reorganization that moved two platform engineers to product teams. The Backstage version in production was fourteen months behind the current release. Updating required retesting all fifteen plugins because the Backstage plugin API had introduced three breaking changes across the skipped releases, and five of the nine product-team-contributed plugins had no documented owner and no test suite. Nine of the fifteen plugins were effectively unmaintained — the on-call rotation plugin broke when PagerDuty changed their API schema and went unrepaired for eleven weeks, the cost explorer plugin had a rendering bug that made cost breakdowns unreadable on Safari and had sat in the issue tracker for four months, and the Terraform Cloud plugin lost its authentication token when the credentials were rotated and nobody remembered where the token was configured.

The service catalog, which had started as the most useful feature, was 40% stale. Teams had registered services correctly when onboarding a new service — the template-based service creation workflow enforced catalog registration — but had not updated catalog entries when changing service ownership after team reorganizations, when adding new upstream or downstream dependencies, or when deprecating services that had been replaced. The catalog showed 127 registered services; 51 had ownership information that was at least one team reorganization out of date, and 23 were services that had been replaced by successors but remained registered as active. The two remaining platform engineers spent 60% of their time responding to questions ("who owns this service?", "why is this plugin broken?", "how do I update the catalog entry?", "when are we upgrading Backstage?") and 40% on maintenance of the most critical plugins. New capability development had stopped entirely.

Time-to-first-PR for new engineers, which had been one day at the platform's peak, had drifted back to three days as templates went stale and setup documentation fell behind the current stack versions. A new engineer joining the data platform team found that the Python data pipeline template used a Python 3.9 base image when the team had moved to Python 3.12, required a manual step to configure the new database connection pooling library the team had adopted four months earlier, and linked to a Confluence page that had been deleted. The original decision — why Backstage rather than Port.io, what the platform team headcount commitment was, what "success" meant at eighteen months, what the trigger for a platform reassessment was — was in a Notion page that had last been edited twenty-six months earlier and had zero views in the last eight months.

The PaaS that couldn't satisfy the enterprise compliance requirement

A 20-person developer tools startup chose Railway for its infrastructure. The decision was made in a Friday-afternoon Slack thread: the engineering team needed a deployment platform, the CTO had used Railway for a side project and found it excellent for the one-engineer use case, the pricing was straightforward, the deployment workflow was a single git push, and the alternative — setting up ECS with Fargate, VPCs, load balancers, and Terraform state management — was three weeks of work for a team that needed to ship a product. The decision was correct at 20 people. Railway's constraint surface was invisible: the team was not yet thinking about VPC isolation, not yet dealing with enterprise security questionnaires, not yet operating at a scale where the absence of fine-grained IAM controls was a gap rather than an acceptable simplification.

At 55 people and 18 months in, the company's sales team closed a term sheet with a mid-market enterprise customer that would represent 40% of ARR. The security questionnaire arrived during legal review. Item 3.4: "Does your infrastructure use network-level isolation (VPC or equivalent) with documented ingress/egress rules?" Railway's architecture is multi-tenant shared infrastructure; VPC isolation is an Enterprise plan feature with a minimum commitment of $2,000 per month and a 30-day activation lead time. Item 7.2: "Where is customer data stored and processed? Provide the AWS region or equivalent." Railway's deployment regions are named by geography (US West, EU West, Asia Pacific) but the specific data center and AWS region are not disclosed in Railway's standard documentation. Item 12.1: "Do you maintain a vendor assessment for all sub-processors with access to customer data?" Railway qualifies as a sub-processor; the Railway SOC 2 Type II report was available under NDA but Railway did not appear on the company's existing sub-processor list.

The infrastructure migration to ECS/Fargate was scoped at four engineering days. The actual elapsed time was three weeks, and the scope expansion traced to a single undocumented pattern: three services had hardcoded Railway service names in their service-to-service call configuration rather than environment variables pointing to configurable endpoints. Railway resolves inter-service calls using an internal DNS scheme (servicename.railway.internal) that is private to the Railway deployment environment. The team had understood this as "internal networking" without documenting that it was Railway-specific DNS resolution. When the first service was migrated to ECS, its downstream callers — still on Railway — could not reach it because the ECS service had a different endpoint scheme. The ECS service could not be migrated without migrating all its callers simultaneously, because Railway's internal DNS had no equivalent in the ECS networking configuration and no environment variable abstraction existed at the call sites.

The three-week migration replaced what should have been a configuration change. The ECS migration itself — Fargate task definitions, ALB setup, VPC creation, security group rules, IAM roles, Route 53 records — took four days as scoped. The remaining eleven days were spent tracing the hardcoded Railway DNS references across 23 service repositories, replacing them with environment-variable-based service endpoints, testing that the service mesh worked correctly in the new configuration, and navigating the dual-environment period during which some services were on Railway and others on ECS and inter-service calls had to traverse both environments through a temporary proxy. The original decision — why Railway rather than a self-hosted alternative, what the network isolation model meant for future compliance requirements, what the migration path was if the team needed VPC isolation, what the trigger for migrating was — was in a Slack thread from eighteen months earlier that the CTO retrieved only after the migration was underway to understand what assumptions the original choice had been based on.

Both outcomes share the same structural cause. The 45-person startup's Backstage implementation was not wrong at four platform team engineers; it was right, and would have remained viable with a documented maintenance cost model that made the staffing dependency explicit and a written trigger for reassessment when maintenance overhead exceeded the threshold. The 20-person startup's Railway deployment was not wrong at 20 people; it was right, and would have remained manageable with a documented migration path that captured the Railway-specific assumptions in the codebase and the compliance requirements that would require leaving Railway. What was missing in both cases was the platform engineering decision record: the reasoning that would have made the ceiling visible before it was exceeded, the maintenance model that would have prevented the platform from being extended past the team's capacity to maintain it, and the trigger criteria that would have initiated a reassessment before a crisis — a platform team reduction or an enterprise compliance requirement — forced one.

Three structural properties that are set at platform selection time

1. The self-service ceiling and the golden-path breadth

Every internal developer platform has a self-service ceiling: the set of developer infrastructure actions that engineers can complete without filing a ticket to the platform team, waiting for manual approval, or asking on Slack. The ceiling is determined at selection time by the platform's design scope — what actions the platform was built or configured to support — and expands slowly as the platform team adds new capabilities. Actions below the ceiling are self-service; actions above it require human intervention. The self-service ratio — the fraction of total developer infrastructure requests completed without human intervention — is the primary usability metric for the platform and is directly determined by where the ceiling is set.

The golden-path breadth determines the ceiling's practical scope: it is not enough for the platform to theoretically support an action; the action must be documented in a golden path that a developer can follow without prior platform knowledge. A Backstage template that creates a new TypeScript API service is only part of the golden path; the golden path also includes the steps to provision the service's database, configure its secrets, set up its CI/CD pipeline, register it in the service catalog, add it to the on-call rotation, and link it to the cost center. If any of these steps requires a Slack message to the platform team, the self-service ceiling for new service creation is not "create a new TypeScript API service" — it is "create a new TypeScript API service skeleton without a database, secrets, CI/CD, or monitoring." The gap between the theoretical ceiling (what the platform can do) and the practical ceiling (what the platform guides a developer through without human intervention) is where most platform teams' self-service ratios fall short.

Document the self-service ceiling explicitly at platform selection time: which actions are within scope for the current platform (developers can complete without human intervention) and which are explicitly out of scope (require platform team involvement). The out-of-scope actions should be documented with the rationale for why they are out of scope — too infrequent to automate, too high risk to allow without human approval, blocked by a compliance requirement that requires human review — so that future platform extensions can be prioritized against the documented gaps. The ceiling should also include the maintenance commitment: which golden paths have a documented owner, what the freshness policy is (templates are updated within two weeks of a new LTS version of the runtime), and what happens to golden paths when the platform team changes. The developer experience decision record governs the local development environment; the platform engineering decision record should document the boundary between local development environment setup (governed by the DX record) and the platform's managed environment provisioning, so that new engineer onboarding is covered end-to-end without gaps between the two records' scope.

2. The build vs. buy vs. PaaS decision and the maintenance cost model

The platform selection decision has three structural options, each with a different maintenance cost model and a different ceiling type. Building a custom IDP (Backstage, custom portal) requires a platform team to build and maintain the abstraction layer; the ceiling is the platform team's engineering capacity. Buying a vendor IDP (Port.io, Cortex, Roadie managed Backstage) transfers the portal maintenance to the vendor but requires paying for the service and accepting the vendor's feature roadmap; the ceiling is the vendor's product scope and the exit cost of migrating away from the vendor's data model. Using a PaaS (Railway, Render, Fly.io, Heroku) transfers the infrastructure abstraction to the vendor; the ceiling is the PaaS's infrastructure capabilities, which may not satisfy compliance, scale, or customization requirements at larger team sizes.

The maintenance cost model is not the same as the initial build cost. A custom Backstage implementation costs four to six months of a two-to-four person platform team to build; the ongoing maintenance cost is one to two engineers of platform team capacity per year, plus additional capacity for each plugin beyond the official ecosystem. A vendor IDP costs zero to build and a vendor-negotiated annual contract to maintain, plus the engineering time spent configuring integrations and keeping the catalog data current. A PaaS costs zero to set up and a usage-based fee to run, but the maintenance cost is dominated by migration cost when the PaaS ceiling is reached — the migration from Railway to ECS that cost eleven days of unplanned work rather than four days of planned work is a maintenance cost that would have been visible if the migration path had been documented at selection time.

Document the maintenance cost model explicitly at selection time: the expected annual engineering cost of maintaining the platform at the current team size, the cost at projected team size in two years, and the specific costs that scale with team size (plugin maintenance scales with the number of plugins, which scales with the number of service types; catalog freshness cost scales with the number of registered services and the frequency of team reorganizations; PaaS migration cost scales with the number of services and the degree of PaaS-specific convention used in the codebase). The maintenance cost model is the number that makes the build-vs-buy trade-off legible: a custom Backstage implementation that costs $400k per year in platform team salaries to maintain is not obviously cheaper than a $150k/year vendor IDP contract, even if the initial build cost was zero and the vendor contract was not. The comparison must be made at the total cost of ownership level, not the initial build cost level. The infrastructure-as-code strategy decision record governs the IaC tooling and Terraform module structure; the platform engineering decision record should document which infrastructure provisioning actions are handled by the platform (self-service via the IDP) and which are handled by the IaC tooling directly (requiring an engineer to run Terraform), so that the boundary between platform-managed and engineer-managed infrastructure is explicit.

3. The onboarding time floor and the environment parity gap

The onboarding time floor is the minimum elapsed time from a new engineer's first day to their first pull request merged to production, given a functioning platform. The floor is set by two factors: the number of manual steps in the onboarding sequence (each manual step adds waiting time — for credentials, for access approvals, for environment provisioning) and the environment parity gap (if the local development environment does not match production, the new engineer will spend additional time debugging failures that are environment artifacts rather than code bugs). The floor is a measurable number — the 75th percentile of time-to-first-PR across the last ten new engineers — and it changes as the platform is extended or allowed to drift.

Document the target floor at platform selection time. The target should be expressed in hours, not days: "a new engineer should be able to submit their first meaningful pull request within eight hours of their first day" is more useful than "new engineers should be productive within one day," because it forces the platform team to examine each step in the onboarding sequence and ask whether the step can be automated, eliminated, or parallelized with other steps. A target of eight hours measured against an actual 75th percentile of 32 hours reveals that the platform's contribution to onboarding is less than the target, and the gap should be traced to specific steps — waiting for Vault access provisioning (four hours), waiting for the database provisioning pipeline to complete (three hours), manually configuring the local development environment because the setup script does not handle the engineer's laptop architecture (six hours). Each identified step is a platform gap that the team can address in priority order.

The environment parity gap is the set of behavioral differences between the environment a developer runs locally or in a development cluster and the environment that runs in production. Differences that produce bugs undetectable in the development environment and visible only in production create a specific failure mode: the code is correct in the environment where it was developed and incorrect in the environment where it runs. Document the known parity gaps at platform selection time: the runtime version differences (development uses Python 3.12 on the developer's local machine; production uses the Fargate task definition's base image, which is updated on a separate cadence), the network topology differences (development uses localhost service discovery; production uses internal DNS that is not reachable from the developer's machine), the external service differences (development uses mocked payment processors and SMS gateways; production uses the live services). The container orchestration decision record governs the production container runtime; the platform engineering decision record should document the expected parity gap between the local development environment and the production runtime, and the compensating controls for each gap (the integration test suite that covers the production runtime's specific behavior, the staging environment that runs on the same container runtime as production, the diff documentation that new engineers receive at onboarding to understand the gap before they hit a parity-derived bug in production).

The five ADR sections for a platform engineering decision

1. Platform scope and self-service ceiling

Document the defined scope of the platform: the specific infrastructure actions that are within the platform's self-service scope, and the actions that are explicitly out of scope for the current platform version. For a Backstage-based IDP: "creating a new service from a template (TypeScript API, Go gRPC, Python data pipeline) is within scope; the template provisions the service repository, the CI/CD pipeline, the staging environment, and the service catalog entry automatically. Provisioning a new database for an existing service is within scope via the database provisioning template. Managing the production Kubernetes cluster's resource limits for an existing service is out of scope for self-service and requires a platform team ticket." For a PaaS-based platform: "deploying a new service version is within scope via git push to the main branch. Provisioning a new Railway database instance is within scope via the Railway dashboard. Configuring custom network routing between services is out of scope via the PaaS dashboard and requires Terraform configuration by the platform team."

Document the self-service ratio target: the fraction of developer infrastructure requests that should be completable without human intervention. Measure the actual self-service ratio at platform launch and at 90-day intervals. The target should be at least 80% for the most common infrastructure actions (deploying a service, accessing service logs, provisioning a development database, rotating development secrets) and below 50% is a signal that the platform's golden-path coverage is insufficient for the team's actual infrastructure needs. A self-service ratio measured by ticket volume (platform tickets as a fraction of total infrastructure requests) is more reliable than a self-service ratio measured by survey ("do you find the platform easy to use?") because ticket volume is an objective measure of the actions the platform failed to cover, and the ticket subject lines reveal the specific golden-path gaps that drive the most human intervention.

Document the golden-path ownership model: for each golden path, who is the documented owner, what is the freshness policy (how frequently the template and documentation are reviewed for currency), and what is the process for deprecating a golden path when the underlying technology or convention changes. Golden paths without owners and without freshness policies drift — the Python 3.9 template that should have been updated to Python 3.12 eight months ago, the database provisioning template that still uses the old connection pooling library, the on-call rotation configuration script that hardcodes the PagerDuty escalation policy ID that was changed during a team reorganization — and a 40% stale golden-path library provides worse onboarding than no golden path at all, because it directs new engineers into wrong configurations that work in development and fail in production. The CI/CD pipeline decision record governs the pipeline configuration; the platform engineering decision record should document which pipeline steps are platform-managed (centrally maintained, applied to all services automatically) and which are service-managed (configured per-service by the service team), because platform-managed pipeline steps that require per-service customization are a common source of onboarding friction when the customization mechanism is not documented in the golden path.

2. Build vs. buy vs. PaaS decision and the maintenance cost model

Document the platform selection decision with explicit rejection reasoning for each alternative evaluated. The reasoning should address the maintenance cost model, not only the initial capability match. A decision record that says "Backstage was chosen because it has a plugin ecosystem and a service catalog" is less useful than one that says "Backstage was chosen because it provides a service catalog and a template engine that covers the team's four primary service types, and the plugin ecosystem reduces the custom development required for the Datadog, PagerDuty, and Terraform Cloud integrations. Port.io was evaluated and rejected because its catalog data model requires a per-entity license that would cost $X at the projected 150-service catalog size and the vendor lock-in risk was higher than the build cost savings justified at the current team size. The maintenance cost model for the Backstage implementation is an estimated 1.5 platform engineers of annual capacity, assuming the team maintains the ten official-ecosystem plugins and three custom plugins and updates the Backstage version annually. This model is valid as long as the platform team headcount remains at three or above; if the platform team falls below three, the annual update cadence will be at risk and the custom plugin maintenance will likely drift."

Document the vendor dependency risk for vendor IDP and PaaS options: the exit cost of migrating away from the vendor if the vendor is acquired, changes pricing in an incompatible direction, or deprecates features the platform depends on. For a PaaS, the exit cost has two components: the infrastructure migration cost (standing up equivalent infrastructure on a new provider) and the codebase migration cost (removing PaaS-specific conventions from service code). The codebase migration cost is the component most frequently underestimated — Railway-internal DNS references, Heroku-specific config vars, Render-specific environment variable names in CI scripts — because PaaS-specific conventions accumulate invisibly over time and are discovered only during migration. Document the PaaS-specific conventions in use at selection time and review the list at platform reassessment milestones to assess how much the migration cost has grown.

Document the scale thresholds at which the platform selection should be reassessed: the team size, service count, or compliance requirement that would require migrating to a more capable platform. These thresholds are guesses at selection time — the team cannot know when compliance requirements will appear or how fast the service catalog will grow — but having a documented guess creates a review trigger that prevents the threshold from being reached without awareness. "The current Railway-based platform should be reassessed if the team exceeds 40 engineers, if the service count exceeds 30, or if an enterprise customer's security questionnaire requires network-level isolation" is more useful than no documented threshold, even if the actual threshold turns out to be 55 engineers and a SOC 2 audit. The security architecture decision record governs the threat model and compliance requirements; the platform engineering decision record should reference the security record's compliance scope and document which compliance requirements the current platform satisfies and which would require a platform migration or an enterprise plan upgrade.

3. Onboarding sequence and time-to-first-PR target

Document the complete onboarding sequence: every step a new engineer must complete from laptop receipt to first pull request merged to production, including the waiting steps (waiting for credential provisioning, waiting for access approvals, waiting for environment setup to complete) and the manual steps (steps that require human assistance or judgment). The sequence should be validated on a freshly provisioned machine before the platform launches and re-validated at each platform version update, because the most common onboarding failures are setup steps that work on the platform engineer's machine (which has cached credentials, pre-installed tools, and prior environment configuration) but fail on a fresh machine (which starts from zero). The validation should be performed by a new engineer or an engineer unfamiliar with the platform, not by the platform team member who wrote the documentation — cognitive bias makes documentation gaps invisible to the author.

Document the time-to-first-PR target with the measurement methodology: how elapsed time is measured (from the new engineer's first Slack message to the time the first PR is merged, reported as the 75th percentile of the last ten new engineers), what counts as a "meaningful" first PR (a change to service code, not a documentation fix or README update), and the process for investigating outliers (engineers whose time-to-first-PR exceeds twice the 75th percentile should have a retrospective conversation with the platform team to identify the specific steps that added time). The 75th percentile matters more than the median because slow onboarding outliers indicate platform gaps — the engineer who spent two extra days debugging a parity gap between the development and production environments identifies a specific fix that will improve every subsequent new engineer's experience; the engineer who needed only half a day confirms that the fast path is working but does not reveal the gaps in the slow path.

Document the environment parity policy: which differences between the development environment and the production environment are documented and accepted, and which are unacceptable. Accepted parity gaps should have compensating controls documented: if the development environment uses an in-memory mock for the payment processor while production uses the Stripe API, the compensating control is an integration test suite that runs against the Stripe API in CI but not in local development. Unacceptable parity gaps — a runtime version difference that causes different JSON serialization behavior, a network topology difference that causes different DNS resolution results — are gaps that the platform should eliminate rather than document as accepted. The acceptance criterion for an environment parity gap is that the gap cannot cause a production-only bug that passes the local development test suite; if it can, it is unacceptable regardless of the cost to eliminate it. The disaster recovery decision record governs the recovery infrastructure; the platform engineering decision record should document whether the development and staging environments use the same recovery infrastructure as production (so that recovery procedure testing is valid) or are simplified environments that do not represent the production recovery scenario.

4. Platform maintenance model and contribution governance

Document the platform maintenance model: who is responsible for keeping the platform current, what "current" means (the Backstage version is within two major releases of the current release, the golden-path templates use the current LTS version of each runtime, the service catalog entries are reviewed and updated at team reorganization events), and what the process is for addressing platform debt that accumulates faster than the maintenance budget allows. The maintenance model must be realistic about the platform team's capacity: a Backstage implementation that requires 1.5 engineers of annual maintenance capacity is not sustainable with a single platform engineer who has other responsibilities, and writing down the requirement makes the resourcing gap visible rather than discovering it when nine of fifteen plugins are unmaintained.

Document the contributor model: the process by which product engineers can contribute new golden paths, new catalog integrations, or new plugin capabilities to the platform, and the review criteria that the platform team applies to contributions. An open contribution model (any engineer can add a golden path by submitting a pull request to the platform repository) lowers the platform team's new capability development cost but increases the maintenance cost (every contribution adds to the maintenance surface and requires the platform team to commit to keeping the contribution current). A closed contribution model (only the platform team adds capabilities) reduces maintenance cost but limits the platform's capability growth to the platform team's engineering capacity. The right model depends on the platform team's capacity and the pace at which the organization's infrastructure needs evolve: a team with high infrastructure churn needs a contribution model that allows product engineers to add capabilities without waiting for the platform team's roadmap. Document the contribution boundaries — which types of contributions are welcome, which require platform team involvement to ensure system-wide consistency — so that product engineers know which platform gaps they can close themselves and which require a platform team request.

Document the deprecation policy for golden paths and platform capabilities: the process for retiring a golden path that is no longer the recommended approach, the notice period for engineers using the deprecated path, and the migration assistance the platform team provides to teams moving from the old path to the new one. A platform without a deprecation policy accumulates an ever-growing library of golden paths, many of which are superseded but remain documented as if they are current — the Dockerfile that uses Python 3.9 that should have been deprecated when the team moved to 3.12, the service template that uses the old database connection pooling library, the CI pipeline configuration that uses the deprecated secrets injection pattern. Engineers who are not actively following platform updates cannot distinguish the current recommendation from the superseded one without asking the platform team, which is precisely the human intervention the platform was intended to eliminate. The multi-tenancy decision record governs tenant isolation; the platform engineering decision record should document whether golden paths for new service creation enforce tenant isolation at the service level (by the service template requiring the tenant context parameter from day one) or leave tenant isolation to be added later by the service team, since the latter pattern frequently results in tenant isolation being omitted from the initial implementation and added only when a cross-tenant access bug is discovered in production.

5. Platform migration trigger criteria and scale thresholds

Document the observable conditions that require a platform migration decision — not a discussion, a decision. Observable conditions are measurable: "time-to-first-PR exceeds 24 hours at the 75th percentile for three consecutive quarters" (measurable from onboarding records), "self-service ratio falls below 70% for the top-10 developer infrastructure actions" (measurable from platform ticket volume), "platform maintenance overhead exceeds 50% of platform team capacity for two consecutive quarters" (measurable from platform team time tracking), "an enterprise customer security questionnaire identifies a capability gap that the current platform cannot satisfy without a vendor tier upgrade or migration" (observable from the deal pipeline). The migration trigger should also include a team-size threshold: "when the engineering team exceeds 60 engineers, reassess the platform against the capabilities required for that scale and the maintenance cost at that scale."

Document the pre-evaluated migration paths at selection time: if the current platform reaches its ceiling, what is the most likely next platform and what is the estimated migration effort? For a PaaS-based platform: the migration path is cloud-native IaC (ECS/Fargate, GKE, or AKS with Terraform); the estimated migration effort at the current team size and service count is four engineering days for the infrastructure migration plus one day per service that uses PaaS-specific internal networking conventions. For a Backstage-based IDP: the migration path if the platform team headcount cannot sustain the maintenance burden is a managed Backstage vendor (Roadie) or a simpler IDP vendor (Port.io); the migration effort is a data export from the existing catalog, a configuration of the new platform, and a redirect of existing golden paths to the new system. The pre-evaluated migration path does not commit the team to the migration — it establishes the direction and the cost estimate before the migration becomes urgent, so that the migration decision can be made rationally rather than under the pressure of an enterprise deal's security questionnaire deadline.

Document the migration authorization process: who is responsible for triggering a platform migration review when the criteria are met, who must approve the migration, and what evidence is required. The migration review should happen during normal planning cycles, not as a special emergency project — if the trigger criteria require a migration review, the review should happen at the next sprint planning or quarterly planning session, not in an ad-hoc meeting called because an enterprise deal is at risk. The API gateway decision record governs the ingress and routing infrastructure; a platform migration that changes the compute or networking model typically requires coordinating with the API gateway configuration, since routing rules, TLS termination, and health check endpoints may be defined in the platform layer and need to be reproduced in the new platform. The observability platform decision record governs the metrics, logs, and tracing infrastructure; a platform migration that moves services from a PaaS to a cloud-native runtime typically requires reconfiguring the log shipping, metrics collection, and tracing instrumentation that was previously handled by the PaaS's built-in observability integration.

The platform decision buried in your AI chat history

Platform engineering decisions are made in AI chat conversations. The Backstage evaluation sprint produces several ChatGPT or Claude sessions: a comparison of Backstage, Port.io, and Cortex against the specific team's requirements; a conversation about whether Backstage's plugin ecosystem covers the team's specific integrations (Datadog, PagerDuty, Terraform Cloud); a session estimating the maintenance cost of a custom plugin versus using the official ecosystem plugin; a follow-up conversation about what "platform team headcount" is required to keep Backstage current. The PaaS evaluation produces similar sessions: a comparison of Railway, Render, and Fly.io against the team's budget and scale requirements; a conversation about what Railway's network isolation model means for future SOC 2 compliance; a session about what the migration path from Railway to ECS would cost at the current service count. Those conversations contain the reasoning that makes the platform decision legible to a future engineer — the alternatives evaluated, the specific capability gaps that drove the selection, the maintenance cost assumptions that justified the choice, and the scale scenarios that were explicitly in scope and out of scope for the initial platform version.

The WhyChose open-source extractor recovers exactly these platform design conversations from your AI chat history — the IDP comparison, the maintenance cost estimation, the compliance impact assessment that shaped the current platform architecture. That reasoning is what the next platform engineer needs when they inherit a Backstage implementation where nine of fifteen plugins are unmaintained and the version is fourteen months behind: not the current state of the platform, which they can read from the repository, but the original reasoning about why the platform was built on Backstage rather than an alternative, what the maintenance cost model assumed, and what was identified as the trigger for reassessment. Without the record, the new platform engineer faces the same open questions as the team that built it — was the original choice right? should the team migrate? is the maintenance overhead normal for a Backstage implementation or a signal that something went wrong? — without access to the context that made those questions answerable at selection time.

Further reading