Build an IDP that accelerates developer productivity. Covers golden paths, service catalogs, self-service infrastructure, and platform team structure.
Platform engineering is the practice of building a coherent, reusable, and self-service foundation for software teams to deliver applications faster and more reliably. It matters when teams struggle with inconsistent deployments, fragmented tooling, ad-hoc infrastructure, and slow onboarding—when developers spend more time configuring their environment than writing code.
An internal developer platform (IDP) is a collection of standardized services, tools, and workflows that abstract away operational complexity. It enables developers to deploy, monitor, and operate applications with minimal effort, using a consistent interface across services.
The core of the platform is a platform API that exposes a domain-specific language for developers to declare their application’s intent. This API is typically a RESTful service, accessed via curl, http, or a client library.
POST /platform/v1/applications
Content-Type: application/json
{
"name": "order-service",
"source": {
"type": "git",
"url": "https://github.com/acme/ecommerce-order-service.git",
"branch": "main"
},
"runtime": "nodejs18",
"environment": "production",
"resources": {
"memory": "4Gi",
"cpu": "2",
"database": {
"type": "postgres",
"version": "15",
"size": "10GB"
},
"ingress": {
"host": "orders.acme.com",
"tls": true
}
}
The platform responds with a 201 Created and a Location header pointing to the application’s status endpoint.
HTTP/1.1 201 Created
Location: /platform/v1/applications/ord-7a2d3c
{
"id": "ord-7a2d3c",
"name": "order-service",
"status": "provisioning",
"created_at": "2024-03-15T10:32:14Z",
"links": {
"self": "/platform/v1/applications/ord-7a2d3c",
"logs": "/platform/v1/applications/ord-7a2d3c/logs",
"deployments": "/platform/v1/applications/ord-7a2d3c/deployments"
}
}
The platform tracks state through a status field, which may be one of: provisioning, ready, deploying, failed, scaling, upgrading.
To deploy a new version of an application, developers send a POST to the /deployments endpoint with a Git reference.
POST /platform/v1/applications/ord-7a2d3c/deployments
Content-Type: application/json
{
"source": {
"commit": "a3f4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2",
"branch": "main",
"tag": "v1.2.3"
},
"environment": "staging",
"config": {
"LOG_LEVEL": "info",
"CACHE_TTL": "300s"
}
}
The platform orchestrates the deployment by:
runtime.Deployment and Service manifest using kubectl.kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service-staging
namespace: orders
spec:
replicas: 3
selector:
matchLabels:
app: order-service
environment: staging
template:
metadata:
labels:
app: order-service
environment: staging
spec:
containers:
- name: app
image: acme/order-service:v1.2.3
ports:
- containerPort: 8080
env:
- name: LOG_LEVEL
value: "info"
- name: CACHE_TTL
value: "300s"
EOF
The platform updates the deployment status and sends a 202 Accepted response with a Location header pointing to a polling endpoint.
HTTP/1.1 202 Accepted
Location: /platform/v1/deployments/dpl-9b8a7c
{
"id": "dpl-9b8a7c",
"application": "ord-7a2d3c",
"status": "started",
"started_at": "2024-03-15T10:33:02Z",
"links": {
"poll": "/platform/v1/deployments/dpl-9b8a7c/poll",
"logs": "/platform/v1/deployments/dpl-9b8a7c/logs"
}
}
The deployment is asynchronous. Clients poll the poll endpoint until the status becomes completed, failed, or canceled.
Each application can have multiple environments: development, staging, production, canary, preview. The platform ensures that each environment has its own:
Secret resource in Kubernetes)A developer creates a new environment by sending a PUT to /environments/{name}.
PUT /platform/v1/environments/staging
Content-Type: application/json
{
"application": "ord-7a2d3c",
"config": {
"LOG_LEVEL": "debug",
"FEATURE_FLAGS": {
"checkout_v2": true,
"invoice_pdf": false
}
},
"scale": {
"replicas": 5,
"memory": "8Gi"
}
}
The platform performs the following actions:
ConfigMap with the config object.Deployment replica count and resource limits.Service to route traffic to the new replicas.Ingress resource with the host and TLS configuration.The platform also maintains a environment matrix, a table of all environments per application, including:
When an environment fails, the platform emits a status event to a message broker (e.g., Kafka or RabbitMQ), which triggers alerts.
Applications require external resources: databases, message queues, caches, object storage. The platform provides a declarative way to provision and configure them.
For example, a developer adds a redis service to their application’s configuration:
"resources": {
"database": {
"type": "postgres",
"version": "15",
"size": "10GB"
},
"cache": {
"type": "redis",
"version": "7",
"size": "2GB"
},
"message_queue": {
"type": "kafka",
"version": "3.6",
"partitions": 12,
"replication": 3
}
}
The platform:
Service of the requested type in the appropriate cloud provider.Secret to the application namespace containing connection details (host, port, credentials).env block with the following keys:DATABASE_URL=postgresql://db-ord-7a2d3c-staging:5432/order_service
REDIS_URL=redis://cache-ord-7a2d3c-staging:6379/0
KAFKA_BROKERS=kafka-ord-7a2d3c-staging:9092
The platform also supports resource templates—reusable configurations for common patterns.
{
"name": "high-availability-postgres",
"type": "postgres",
"version": "15",
"spec": {
"replication": 3,
"backup_schedule": "0 2 * * *",
"persistence": {
"size": "100GB",
"storage_class": "gp3"
},
"monitoring": {
"metrics": ["cpu", "memory", "connections"],
"alerts": {
"high_load": "avg_cpu > 80%",
"long_query": "avg_query_duration > 500ms"
}
}
}
}
When a developer references this template, the platform applies all its fields and adds the template’s metadata to the resource.
The platform provides a unified observability layer. Every application exposes a /metrics endpoint (Prometheus format) and logs to a structured format (JSON).
{
"timestamp": "2024-03-15T10:35:12.345Z",
"level": "info",
"message": "Order created",
"event": {
"order_id": "ord-12345",
"user_id": "usr-67890"
}
}
The platform collects logs from all services and stores them in a centralized system (e.g., Elasticsearch or Loki).
Developers access logs via the platform API:
GET /platform/v1/applications/ord-7a2d3c/logs?from=2024-03-15T10:00:00Z&to=2024-03-15T11:00:00Z&level=error&limit=100
The response includes a next token for pagination.
HTTP/1.1 200 OK
Content-Type: application/json
{
"logs": [
{
"timestamp": "2024-03-15T10:35:12.345Z",
"level": "error",
"message": "Failed to send email",
"service": "order-service",
"trace_id": "trace-a1b2c3",
"context": {
"order_id": "ord-12345",
"error": "timeout",
"details": "Connection timed out after 30s"
}
}
],
"next": "eyJ0aW1lX3N0YXJ0IjogMTQyMzQ1NjAwMCwgImxpbmVzIjogMTAwfQ=="
}
The platform also exposes a tracing API that allows developers to fetch spans for a given trace_id.
GET /platform/v1/traces/trace-a1b2c3
The response includes a list of spans with duration, start time, and metadata.
The platform detects configuration drift by periodically syncing the desired state (from the API) with the actual state in the cluster.
This sync process runs every 5 minutes and detects:
Deployment replicasSecretsConfigMap valuesIngress rulesWhen drift is detected, the platform logs a config_drift event and updates the application’s status to drift_detected.
A common silent failure is missing secrets. If a service requires a DATABASE_URL environment variable, but the Secret for the database is not created, the platform logs:
{
"timestamp": "2024-03-15T10:40:00Z",
"level": "warning",
"message": "Missing required secret",
"context": {
"application": "ord-7a2d3c",
"service": "order-service",
"expected_secret": "db-ord-7a2d3c-staging",
"actual": null
}
}
The platform also supports rollback on failure. If a deployment fails (e.g., health check timeout), the platform:
failed.Deployment manifest to point to the old image.rollback_completed event.{
"timestamp": "2024-03-15T10:41:22Z",
"event": "rollback_completed",
"application": "ord-7a2d3c",
"from": "v1.2.2",
"to": "v1.2.1",
"reason": "health check timeout",
"deployment": "dpl-9b8a7c"
}
The platform is extensible via plugins—self-contained services that integrate with the core platform.
A plugin is a service that exposes a /plugin endpoint and subscribes to platform events via a message broker.
For example, a CI/CD plugin listens to application_created and deployment_started events.
When an application_created event arrives, the plugin:
Makefile and Dockerfile.git and cron.pull_request for the initial main branch.The plugin responds with a 200 OK and returns metadata about the created pipeline.
{
"pipeline_id": "ci-pip-3a4b5c",
"repository_url": "https://github.com/acme/order-service",
"ci_url": "https://ci.acme.com/pipelines/ci-pip-3a4b5c"
}
The platform updates the application’s links with the new pipeline and triggers a pipeline_ready event.
This pattern—event-driven extension—enables teams to add new functionality (e.g., security scanning, cost reporting, documentation generation) without modifying the core platform.
The platform also supports self-healing: when an application fails, it triggers a series of automated actions, such as:
kubectl scale deployment order-service --replicas=6)These actions are defined in a healing.yaml file in the application’s source tree.
healing.yaml
---
- name: "scale-on-failure"
condition: "service_healthy == false"
actions:
- "kubectl scale deployment order-service --replicas=6"
- "curl -X POST https://alerts.acme.com/api/v1/notify -d '{\"title\": \"Scale up\", \"message\": \"Increased replicas\"}'"
- "psql -c 'INSERT INTO healing_events (app, action, time) VALUES (\\\"ord-7a2d3c\\\", \\\"scale-up\\\", now())'"
The platform applies these actions when the condition is met, logging each step.
An internal developer platform is not a collection of tools—it is a system of intent. Developers declare what they want, and the platform delivers it. The platform’s value lies in consistency, self-service, and resilience. It reduces cognitive load, accelerates onboarding, and enables teams to ship faster with fewer errors. Its success is measured not in metrics, but in the quiet confidence of a developer who can deploy a service with a single curl command—and trust that the platform has done the rest.
This page was rewritten on 17 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.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy