Platform Engineering and Internal Developer Platforms
Treating internal infrastructure as a product: paved roads, self-service provisioning, guardrails instead of approval gates, the interfaces a platform exposes, and the reasons platform teams fail to get adopted.
This is a reference for building and operating internal developer platforms—systems that provide teams with self-service capabilities, standardised toolchains, and consistent infrastructure patterns. It matters when organisations need to scale development velocity while maintaining operational reliability across many teams.
Creating a Developer-Friendly API Gateway
Setting up authentication for platform APIs
When exposing platform functionality through HTTP endpoints, the core concern is securing access without overburdening developers. Platform APIs typically require either token-based or certificate-based authentication.
Example configuration for an API gateway using standard OpenAPI/Swagger definitions:
openapi: 3.0.0
info:
title: Internal Developer Platform API
version: 1.0.0
servers:
- url: https://platform.example.com/api/v1
paths:
/deployments:
post:
security:
- bearerAuth: []
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
The API must reject requests with invalid tokens, returning HTTP 401 Unauthorized. The most common failure mode is misconfigured token validation, where a platform returns 200 OK when it should return 401.
Handling rate limiting for platform services
Platform APIs should enforce quotas to prevent abuse. A typical implementation uses an in-memory or Redis-backed counter per user or team.
Example response header for rate limiting:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1678886400
Failure mode: API returns 200 OK even when rate limit is exceeded, causing silent overuse of platform resources.
Managing Developer Workflows and Access
Provisioning user accounts and permissions
Platform access control involves assigning roles to users or teams. The system uses a standard RBAC model where each role has a set of allowed actions.
Example SQL for role assignment:
INSERT INTO platform_user_roles (user_id, role_name, granted_at)
VALUES ('user-123', 'developer', NOW());
The platform should enforce that users cannot perform actions outside their assigned roles. Failure occurs when permissions are not checked properly in the service layer, allowing privilege escalation.
Defining access policies with structured rules
Access control policies are typically stored as JSON documents. Example policy structure:
{
"version": "1",
"rules": [
{
"action": "create_deployment",
"resource": "namespace/*",
"principal": "team:frontend",
"effect": "allow"
}
]
}
Policies are validated against a schema. If an invalid field like principal_type is present, the system rejects the policy with HTTP 400 Bad Request.
Implementing Self-Service Infrastructure
Creating standardised deployment templates
Platform users should be able to instantiate pre-defined infrastructure patterns without deep knowledge of underlying systems. A template is a YAML file that defines parameters and resources.
Example deployment template:
apiVersion: platform/v1
kind: DeploymentTemplate
metadata:
name: web-app
spec:
parameters:
- name: replicas
type: integer
default: 2
resources:
- apiVersion: apps/v1
kind: Deployment
spec:
replicas: {{ replicas }}
The platform substitutes {{ replicas }} with the provided value. Failure occurs when a required parameter is missing, causing a validation error in the deployment phase.
Managing service discovery and configuration
Services deployed through the platform must be registered in a consistent way. The platform uses standard Kubernetes labels or annotations to track service metadata.
Example service definition:
apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app.kubernetes.io/name: my-service
platform.io/owner: frontend-team
spec:
ports:
- port: 80
Failure mode: Service registration is skipped, causing the service to be unreachable via standard discovery mechanisms.
Automating Platform Operations
Monitoring and alerting for platform health
Platform components should emit structured logs with consistent formatting. Example log entry:
{
"timestamp": "2023-01-01T12:00:00Z",
"level": "error",
"message": "Failed to provision namespace",
"details": {
"user_id": "user-123",
"request_id": "req-456",
"error_code": "NAMESPACE_CREATION_FAILED"
}
}
Platform health is monitored through standard metrics endpoints. The system should expose /metrics with Prometheus-compatible output.
Handling platform upgrade and rollback
Platform upgrades follow a staged approach. Changes are first applied to a staging environment, then promoted to production with a manual approval step.
Example rollback command:
kubectl rollout undo deployment/platform-api --to-revision=1
Failure mode: Rollback does not restore previous state due to missing configuration in the new version, causing partial service degradation.
Managing Platform Metadata and Documentation
Maintaining consistent metadata schemas
All platform resources must conform to standardised metadata structures. Example:
apiVersion: platform/v1
kind: Resource
metadata:
name: example-service
labels:
platform.io/environment: production
platform.io/team: backend
annotations:
platform.io/description: "A sample service for demonstration"
The platform validates metadata during creation. Failure occurs when an annotation key is not recognized, causing a rejection of the entire resource.
Providing developer-friendly documentation
Platform documentation should be available through standard web interfaces and API endpoints. Example API endpoint:
GET /api/v1/docs/service-types
Accept: application/json
Response format:
[
{
"name": "web-app",
"description": "A containerised web application",
"parameters": [
{
"name": "image",
"type": "string",
"required": true
}
]
}
]
Failure mode: Documentation is not updated after changes, leading to developers using outdated information.
Handling Common Platform Failure Modes
Recovering from partial failures
Platform components may experience partial failure during operations. For example, a deployment might succeed in creating the service but fail to create the associated secret.
Example recovery procedure:
kubectl get deployment my-service -o yaml | grep -A5 "status"
The platform should detect and report partial failures. If an operation fails partway through, it should log what succeeded and what failed.
Managing drift between desired and actual state
Platform resources may drift from their intended configuration. The system uses standard reconciliation loops to maintain consistency.
Example drift detection:
kubectl diff -f deployment.yaml
If drift is detected, the platform should either auto-correct or notify the user about the mismatch.
Dealing with cascading failures
Platform services often depend on each other. When one service fails, it can impact others. The system should implement circuit breaking and timeout handling.
Example timeout configuration:
timeout: 30s
retries: 3
retry_backoff: 1s
Failure mode: A single failing dependency causes the entire platform to become unresponsive due to lack of timeouts or circuit breaking.
Handling version compatibility
Platform components must maintain backward compatibility. When introducing breaking changes, the system should provide migration paths.
Example versioning in API calls:
GET /api/v1/deployments?api-version=2023-01-01
The platform should return HTTP 410 Gone for deprecated endpoints and provide clear deprecation notices.
This page was rewritten on 15 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.