Updated September 2025
Managing Kubernetes configs starts innocent enough.
You've got 3 services, each needs a deployment YAML. No big deal. Then it's 10 services. Then 25. Before you know it, you're copy-pasting the same YAML blocks like a madman, changing service names and ports, and praying you didn't miss anything.
I missed a fucking quote mark in one ConfigMap and took down 6 services in staging. Spent 3 hours debugging it because they all looked identical. That's when I finally learned Jsonnet.
Jsonnet is Google's attempt to fix this disaster.
They created it in 2014 because even Google got tired of copy-pasting JSON. It's basically JSON with programming features
- variables, functions, loops, inheritance. Instead of maintaining 50 nearly-identical YAML files, you write code that generates them.
The Actual Problem This Solves
Here's what happens: you start with 5 services, each needs deployment + service + ingress YAML.
That's 15 files. No problem. Then product wants 20 services. Now it's 60 files. CEO talks about "microservice architecture" and suddenly you're managing configs for like 35 services. That's over 100 YAML files that are 90% identical.
Need to change resource limits across all services? Hope you like editing 35 files and not fucking up a single one. Because I promise you'll mess up at least 3 and spend your afternoon debugging why some random service won't start.
// This generates all your service configs from one template
local make
Service(name, port, replicas) = {
deployment: {
metadata: { name: name },
spec: {
replicas: replicas,
template: {
spec: {
containers: [{
name: name,
image: 'us-central1-docker.pkg.dev/myproject/%s:latest' % name,
ports: [{ containerPort: port }],
resources: if std.ends
With(name, '-prod') then {
limits: { memory: '2Gi', cpu: '1' }
} else {
limits: { memory: '512Mi', cpu: '0.5' }
}
}]
}
}
}
},
service: {
metadata: { name: name },
spec: {
selector: { app: name },
ports: [{ port: port, targetPort: port }]
}
}
};
// Generate configs for all services
{
'user-service.json': make
Service('user-service', 8080, 3),
'order-service.json': make
Service('order-service', 8081, 5),
'payment-service.json': make
Service('payment-service', 8082, 2)
}
Why Not Just Use Helm?
Helm is fine if you're just installing community charts. But the moment you need custom logic, Go templates become fucking miserable. Ever tried debugging `{{ range $key, $val := .
Values.env }}{{ if ne $val "" }}{{ $key }}={{ $val }}{{ end }}{{ end }}`? I have. At 3am. While production was down. Fun times.
Jsonnet gives you actual programming. Need a loop? Write a loop. Need conditionals? Write if/else. Need to import shared code? Import it. No template gymnastics required.
The Implementation Mess
Here's where Jsonnet gets annoying. There are 3 different implementations and picking the wrong one will waste your day:
C++ (original)
- Slow as hell, has security warnings, basically abandoned.
Don't use it.
Go (go-jsonnet)
- Use this one. Way faster than C++, includes a linter, and actually gets updates. When you run
brew install jsonnet
, this is what you get. Current version is 0.20.0 because they're slow at releasing updates.
Sjsonnet (JVM)
- Databricks made this because they needed something faster for their massive configs. Startup time sucks for small stuff but it flies through big codebases. Unless you're generating thousands of files, stick with Go.
Who Actually Uses This Thing
Databricks has something like 40,000 lines of Jsonnet generating hundreds of thousands of YAML files. They switched because managing Spark configs manually was making their engineers hate life.
Grafana built an entire ecosystem around Jsonnet for monitoring stacks. Their Tanka project is basically "Jsonnet for Kubernetes"
- it handles the kubectl integration so you don't have to convert everything manually. Way cleaner than fighting with Kustomize overlays.
The community is small but the people who use it really use it. Not like Helm where half the charts are abandoned.
When to Bother With This
Use Jsonnet if:
- You've got 15+ services with nearly-identical configs
- You need actual programming logic in your configs
- Copy-pasting YAML is driving you insane
- You want to version control your config generation like real code
Don't use Jsonnet if:
- You have like 5 services that never change
- Your team thinks learning new tools is "unnecessary complexity"
- Kustomize already solves your problems
- You need the massive Helm chart ecosystem
The break-even point is roughly "am I spending more time copy-pasting YAML than I would learning Jsonnet?" For most small projects, probably not.