Essay
YAML, JSON & Environment Variables in DevOps
A production-first guide to configuration formats in DevOps — why YAML dominates, where JSON fits, when ENV variables shine, and how real systems actually use all three together.

Introduction
Most production outages caused by configuration are not syntax problems —
they're design problems.
The issue isn't *how* to write config.
The issue is where config lives, how it's structured, and how it flows across environments.
In modern DevOps, three formats dominate configuration:
- YAML
- JSON
- Environment Variables
This post explains:
- why YAML dominates DevOps
- how YAML, JSON, and ENV compare
- how real production systems use all three together
No theory. Only real-world patterns.
Why YAML Dominates DevOps
YAML didn't win because it's perfect.
It won because it fits human + machine workflows better than alternatives.
Why DevOps Tools Prefer YAML
YAML is:
- human-readable
- indentation-based (structure is visible)
- comment-friendly
- good for hierarchical config
That makes it ideal for infrastructure and pipelines, where humans constantly review configs.
Where You See YAML in Real Life
- CI/CD pipelines (GitHub Actions, GitLab CI)
- Kubernetes manifests
- Helm charts
- Ansible playbooks
- Docker Compose
These are reviewed more than they're written, and YAML optimizes for that.
Example: CI/CD Pipeline (YAML)
stages:
- build
- test
- deploy
deploy:
stage: deploy
script:
- docker build -t app:${CI_COMMIT_SHA} .
- docker push app:${CI_COMMIT_SHA}
This reads like a plan — not a data structure.
That's YAML's superpower.
JSON vs YAML vs Environment Variables
These formats are not competitors.
They solve different configuration problems.
1. YAML – Declarative & Structured
Best for:
- Infrastructure definitions
- Pipelines
- Declarative systems
Strengths:
- Easy to scan visually
- Supports nesting naturally
- Supports comments
Weaknesses:
- Indentation-sensitive
- Easy to break with spacing errors
2. JSON – Strict & Machine-Oriented
Best for:
- APIs
- Structured data exchange
- Programmatic configs
Strengths:
- Strict schema
- Easy for machines to parse
- No ambiguity
Weaknesses:
- Verbose
- No comments
- Harder to read for humans
Example: App Config in JSON
{
"database": {
"host": "db.internal",
"port": 5432,
"ssl": true
}
}
JSON shines inside applications, not infrastructure definitions.
3. Environment Variables – Runtime Overrides
Best for:
- Secrets
- Environment-specific values
- Runtime configuration
Strengths:
- Externalized from code
- Easy to change per environment
- Secure when handled properly
Weaknesses:
- Flat (no structure)
- Hard to validate
- Easy to misconfigure
Example: ENV Variables
DATABASE_HOST=db.internal
DATABASE_PASSWORD=secret
NODE_ENV=production
Environment variables are not config files — they are overrides.
The Golden Rule of DevOps Configuration
Structure in files.
Secrets in ENV.
Data contracts in JSON.
Mature systems never rely on a single format.
Real Config Examples (Production Style)
1. CI/CD: YAML + ENV
deploy:
script:
- kubectl apply -f deployment.yaml
variables:
KUBE_NAMESPACE: production
- YAML defines the pipeline
- ENV injects environment-specific values
2. Docker: Dockerfile + ENV
FROM node:20
ENV NODE_ENV=production
CMD ["node", "server.js"]
Runtime values (DB URL, tokens) come from ENV, not baked images.
3. Kubernetes: YAML + ENV + Secrets
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
image: app:1.2.0
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
This is real-world DevOps:
- YAML → structure
- ENV → injection
- Secrets → security
Common Anti-Patterns to Avoid
1. Everything in ENV Variables
❌ Hundreds of ENV vars
❌ No validation
❌ No structure
ENV vars should override, not replace config.
2. Secrets Inside YAML
password: admin123
This is how breaches happen.
Rule:
- YAML for structure
- Secrets managers for secrets
3. JSON for Infrastructure
Possible, but painful.
{
"containers": [
{
"name": "app"
}
]
}
Harder to read, harder to review, harder to maintain.
How Mature Teams Use Configuration
A healthy DevOps setup looks like this:
- YAML → infra & pipelines
- JSON → application config & APIs
- ENV → secrets & environment overrides
- Same code, different config per environment
- No manual edits on servers
Configuration becomes boring and predictable — which is exactly what you want.
Final Takeaway
YAML dominates DevOps because DevOps is human-driven automation.
But real systems don't choose one format.
They combine:
- YAML for clarity
- JSON for contracts
- ENV for runtime flexibility
If your config strategy is intentional,
your deployments become boring,
your rollbacks become safe,
and your incidents become rare.
And that's the real goal of DevOps.