Search across all documentation pages
Pick the small set of workload archetypes your org actually runs.
For most teams that is three: a web API, a background worker, and a scheduled cron job.
Build one template per archetype that takes a handful of inputs and generates complete, policy-compliant manifests.
Ship each template as a versioned Helm chart or Kustomize base, wired into GitOps.
Document the single command or repo-copy that starts each path, and mark the supported escape hatch.
A golden path for a web API accepts a few values and expands into a full deployment set.
# values.yaml - the entire contract for the web-api golden path
name: checkout-api
image: registry.example.com/checkout-api:1.4.0
port: 8080
cpu: "250m"
memory: "256Mi"
minReplicas: 2
maxReplicas: 10The chart template renders a hardened Deployment from those values.
# templates/deployment.yaml (excerpt) - defaults baked in
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.name }}
spec:
replicas: {{ .Values.minReplicas }}
selector:
matchLabels: { app: {{ .Values.name }} }
template:
metadata:
labels: { app: {{ .Values.name }} }
spec:
securityContext:
runAsNonRoot: true
seccompProfile: { type: RuntimeDefault }
containers:
- name: app
image: {{ .Values.image }}
ports: [{ containerPort: {{ .Values.port }} }]
resources:
requests:
cpu: {{ .Values.cpu | quote }}
memory: {{ .Values.memory | quote }}
readinessProbe:
httpGet: { path: /healthz, port: {{ .Values.port }} }The worker archetype drops the Service and probes-on-a-port and instead runs a queue consumer.
# worker path: no inbound Service, scale on queue depth if available
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.name }}-worker
spec:
replicas: {{ .Values.minReplicas }}
template:
spec:
containers:
- name: worker
image: {{ .Values.image }}
args: ["consume", "--queue", "{{ .Values.queue }}"]The cron archetype renders a CronJob with the org's retention and concurrency defaults.
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{ .Values.name }}
spec:
schedule: {{ .Values.schedule | quote }}
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: Never
containers:
- name: job
image: {{ .Values.image }}A developer starts the path by copying a template repo and running one command.
# scaffold a new service on the web-api golden path
platform new web-api --name checkout-api --port 8080
git commit -am "add checkout-api" && git pushArgo CD then reconciles the generated manifests into the target namespace.
Resist the urge to template everything.
Three or four archetypes cover the vast majority of services, and each new one you add is ongoing maintenance.
Name them by developer intent (web API, worker, cron) rather than by Kubernetes object.
The golden path is only as good as the defaults it encodes.
Bake in resource requests, probes, the restricted security context, a default-deny NetworkPolicy, and an HPA.
Encode these once in the template so no developer has to remember them.
Templating produces good defaults, but nothing stops a team from editing the output later.
Pair templates with admission policy (Kyverno or Gatekeeper) so unsafe edits are rejected at apply time.
Templates make the safe thing easy; policy makes the unsafe thing impossible.
Treat each path as software with a semantic version.
When you change a default, bump the chart version and let teams adopt on their own cadence, with a deprecation window for old versions.
A path that is too opinionated becomes a wall the moment a team needs a sidecar or a custom volume.
Provide a documented escape hatch: allow extra manifests in a well-known folder that the path merges in.
Silent default changes break trust when a chart bump alters behavior without warning.
Communicate changes through versioned releases and changelogs, never by editing a shared template in place.
Path sprawl creeps in when every request spawns a new archetype.
Keep the archetype count small and push variation into values, not into new templates.
Skipping policy enforcement lets drift accumulate until the golden path is fiction.
Wire admission control from day one so the generated config stays the applied config.
Raw manifests plus documentation. Fine for a single team or a few services, but it drifts and does not scale to many teams.
A full PaaS or Knative. Higher abstraction that hides Kubernetes almost entirely; great for stateless HTTP but limiting for unusual workloads.
Crossplane or an operator with custom resources. A more powerful, API-driven path where developers submit a custom resource; more capable but more to build and run.
Backstage software templates. A strong interface layer that scaffolds golden-path repos; pair it with the charts and policy described here rather than treating it as the whole platform.
How many golden paths should we have?
Start with the two or three archetypes you run most. Add a new one only when a real, repeated workload does not fit an existing path.
Are golden paths mandatory?
Make them the default and the fastest option, not a mandate. Adoption should come from being easier, backed by policy that blocks unsafe alternatives.
What if a team needs something the path does not support?
Offer a reviewed escape hatch: extra manifests merged by the template, or a documented process to extend the path itself.
Do golden paths replace policy enforcement?
No. Templates set good defaults, and admission policy keeps them enforced after apply. You need both.
Who owns a golden path?
The platform team owns and versions it, treating application teams as customers and folding their feedback into the roadmap.
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026