10 min read

Internal Developer Platforms: What to Abstract and What Not To

Platform EngineeringDevOpsDeveloper Experience

Every company eventually builds an internal developer platform (IDP). Sometimes it is intentional. Often it accretes from scripts, templates, and tribal knowledge. Either way, the question is the same: what should the platform abstract away, and what should developers still see?

Get this wrong in one direction and developers drown in YAML. Get it wrong in the other and they cannot debug anything because the platform hides too much.

What Is an IDP, Really

An IDP is a self-service layer that lets developers deploy, observe, and operate their services without needing deep infrastructure expertise. It is not a PaaS like Heroku. It is an opinionated abstraction over your specific infrastructure.

The core components:

Golden Paths: The 80% Case

A golden path is the blessed way to do something. "If you are building a standard HTTP API, use this template, this pipeline, and these defaults." Golden paths should cover 80% of use cases.

A good golden path:

  1. Scaffolds in minutes: platform new service --name my-api --type http generates everything
  2. Deploys with one command: platform deploy or git push, no manual steps
  3. Includes observability by default: Metrics, logging, tracing, alerts, dashboards
  4. Has secure defaults: TLS, authentication, resource limits, network policies

The goal is that a developer can go from idea to production without reading Kubernetes documentation. Not because Kubernetes is bad, but because their job is building product features, not learning infrastructure.

Escape Hatches: The 20% Case

Golden paths fail when they become golden cages. Every abstraction leaks. Developers need a way to go below the abstraction when the default does not fit.

Escape hatches include:

The rule: the platform should make the standard case easy and the custom case possible. If developers cannot escape the golden path, they will work around the platform entirely (shadow infrastructure), which is worse than no platform.

What to Abstract

Abstract: Boilerplate and repetition. If every service needs the same Dockerfile structure, health check endpoints, logging configuration, and CI pipeline, template it. Developers should not copy-paste infrastructure.

Abstract: Security defaults. TLS certificates, secret injection, network policies, pod security standards. These should be correct by default, not opt-in. Developers should have to work to make things insecure, not to make them secure.

Abstract: Observability wiring. Every service should emit metrics, logs, and traces in a standard format without developer effort. The platform configures the collectors, dashboards, and alerts.

Abstract: Environment parity. Dev, staging, and production should be as similar as possible. The platform manages the differences (resource sizes, replica counts, external dependencies).

What NOT to Abstract

Do not abstract: Application architecture. The platform should not dictate whether you use microservices or a monolith, REST or gRPC, SQL or NoSQL. These are application decisions.

Do not abstract: Business logic deployment. Feature flags, database migrations, and API versioning are the developer's responsibility. The platform provides the mechanism (flag service, migration runner), not the policy.

Do not abstract: Debugging. When something breaks in production, developers need to see logs, exec into pods, query metrics, and trace requests. A platform that hides debugging tools is a platform developers will bypass.

Do not abstract: Cost visibility. Developers should see what their services cost. Hide the complexity of cost allocation, but show the numbers. Teams cannot optimize what they cannot see.

In practice this means the platform owns cost attribution as a first-class feature, not a spreadsheet finance maintains. Tag every resource the platform provisions (cluster, namespace, database, queue) with the owning service and team, and surface a per-service cost dashboard next to the deploy dashboard. The familiar failure mode: the platform provisions RDS instances and EBS volumes on behalf of developers, nobody sees the bill until finance asks why infrastructure spend doubled, and the platform team gets blamed for costs it enabled but never made visible. Show cost per deploy, per environment, per service. Chargeback (billing teams for usage) is optional; showback (visibility without billing) is mandatory.

The Platform Team's Job

The platform team builds the IDP, but their real job is reducing cognitive load for product teams. Measure success by:

If the platform team becomes a bottleneck (every change requires a ticket), the IDP has failed. Self-service is the point.

Build vs Buy

You do not need to build everything. The CNCF landscape has mature options:

Compose these rather than building from scratch. Your platform team's value is in the integration and opinions, not in reimplementing a service catalog.

The sequencing decision matters more than the tooling choice. Buying or building a portal before you have a paved deployment path gives you a beautiful catalog of services that still deploy through snowflake pipelines. The portal is the last mile, not the first. Sequence it: deployment pipeline first (the thing developers touch daily), then observability defaults, then scaffolding, then the portal to tie it together. Each layer earns the trust that makes the next one adoptable. Teams that start with the portal end up with a dashboard nobody opens because the underlying workflows are still painful.

Starting Small

Do not try to build a full IDP on day one. Start with the biggest pain point:

  1. If deployments are manual and error-prone: build the deployment pipeline first
  2. If every team reinvents observability: standardize metrics and dashboards first
  3. If onboarding takes weeks: build service scaffolding first

Solve one problem well, get adoption, then expand. A platform nobody uses is worse than no platform because it creates the illusion of solved problems.

System Architecture

The platform sits between developers and infrastructure: a self-service front end, opinionated pipelines behind it, and shared services underneath.

+----------------+     +------------------+
|  Developer     |---->|  Portal          |
|  CLI or UI     |     |  scaffolding     |
+----------------+     +------------------+
                                |
              +-----------------+-----------------+
              |                                   |
              v                                   v
+------------------+                   +------------------+
|  CI CD Pipeline  |                   |  GitOps          |
|  build and test  |                   |  sync to         |
|                  |                   |  clusters        |
+------------------+                   +------------------+
              |                                   |
              +-----------------+-----------------+
                                |
                                v
                     +------------------+
                     |  Observability   |
                     |  cost dashboards |
                     +------------------+

Developers interact through the portal (Backstage) or CLI: scaffolding a service from templates, browsing the catalog and docs. The CI/CD pipeline builds, tests, and pushes artifacts. GitOps (ArgoCD) syncs desired state to clusters, which is the actual deploy mechanism. Underneath, shared platform services provide observability (metrics, logs, traces with defaults) and cost attribution dashboards per service and team. The platform team owns the integration between these layers; the individual tools are bought or adopted, and the opinions connecting them are the platform.

Scalability

At 10x developers and services, the platform's bottlenecks are queues and controllers. CI runner queues are first: a fixed pool of runners that served 20 developers serializes painfully for 200, and queue wait time becomes the dominant part of deploy lead time. Autoscale runner pools (or move to autoscaled cloud runners) and treat time-in-queue as a platform SLO. The service catalog is second: Backstage ingesting hundreds of entities is fine, but at thousands of services with frequent updates, catalog processing lags and the portal shows stale data. Shard or scale the catalog backend before developers stop trusting it.

At 100x, the constraint is organizational, not technical. Any step that requires a platform team ticket becomes the bottleneck: database provisioning, namespace creation, production access grants. If the platform team must grow linearly with developers, the platform has failed; self-service must absorb the growth. ArgoCD is the technical hotspot at this scale: thousands of Applications overwhelm a single controller instance, so shard by cluster or team. Golden paths face a scaling test too: templates that served 50 similar services strain when 500 teams need variants. The answer is composable templates (a base with opt-in modules) rather than 500 bespoke templates, which is just snowflake infrastructure with extra steps. The horizontal strategy: every human-gated step gets automated or removed, controllers get sharded, and templates stay composable.

Security Considerations

The platform holds the keys to production, so its own security posture matters more than any single service's. Apply least privilege to the platform's service accounts first: the CI system's deployment credentials, ArgoCD's cluster access, and the scaffolding service's cloud permissions should each be scoped to exactly what that component needs. These are the crown-jewel credentials; a compromised ArgoCD with cluster-admin can deploy anything anywhere.

Manage secrets as a platform capability, not a per-team chore. Provide external-secrets or a vault integration as the default path, and make the wrong thing (secrets in repo files, in template defaults, in CI logs) harder than the right thing. Templates deserve review like code: a scaffolding template executes during service creation, so a malicious or compromised template is a code execution vector. Pin template versions, review template changes, and sign them if your threat model warrants it.

Audit everything the platform does: who scaffolded which service, who deployed what to production and when, who was granted break-glass access. This audit trail is both a security control and a compliance artifact. Realistic attack vectors: a developer exfiltrating production secrets through a debug pod the platform provisioned (scope debug access with short-lived credentials); template injection adding a malicious dependency to every scaffolded service (review templates, pin dependencies); and the portal itself becoming an SSRF or auth-bypass target (treat it as a production internet-facing app with its own hardening, not as internal tooling that is implicitly trusted).

Production Checklist

Monitoring signals:

Failure modes seen in production: template drift, where generated services diverge from the golden path over time and upgrades become impossible (mitigate with versioned templates and a documented upgrade path, not with mandates); platform outage blocking all deploys, because the platform became critical path without anyone declaring it so (run CI and GitOps in HA, and document break-glass direct cluster access); silent adoption failure, where the portal shows healthy metrics but teams still deploy by hand (talk to the teams; the metrics will not tell you why).

Runbook notes: the break-glass deploy procedure (direct cluster access when the portal or CI is down) must be documented, access-controlled, and tested, or the first platform outage becomes a full deploy freeze. Template changes roll out like any other production change: versioned, announced, with a migration window. And measure developer satisfaction directly and regularly; it is the only metric that predicts whether the platform survives its next reorg.


The best internal platform is the one developers choose to use, not the one they are forced to use.

More articles