Score: The Workload Specification That Wants to Replace Your Helm Values
Score is a new developer-centric workload spec that separates what your app needs from how it's deployed. Here's an honest deep-dive: what problem it solves, how it works, where it falls short, and whether you should adopt it.
Every few years, someone looks at the state of Kubernetes developer experience and says: "This is too complicated. Developers shouldn't need to know about Deployments, Services, Ingress, PodDisruptionBudgets, and HorizontalPodAutoscalers just to deploy a web app."
Score is the latest serious attempt to solve this problem. And unlike most "Kubernetes for developers" tools, it's not trying to hide Kubernetes — it's trying to separate what your workload needs from how that need is fulfilled in a specific environment.
Let me explain why that distinction matters, and whether Score delivers on its promise.
The Problem Score Is Solving
Talk to any developer who isn't platform-focused. They have one question: "How do I deploy my app?" They don't want to learn Kubernetes. They don't want to maintain 400 lines of Helm chart templates. They don't want to understand the difference between a ClusterIP and a NodePort service.
But platform engineers also have legitimate needs: they need to enforce resource quotas, security policies, network controls, and operational standards. They can't just let developers kubectl apply whatever they want.
This creates a tension. Current solutions:
Option A: Give developers full Kubernetes access. Chaos. Security nightmare. Inconsistent deployments.
Option B: Developers write Helm values files. Still requires Kubernetes knowledge. Values files are environment-specific and get duplicated across dev/staging/prod.
Option C: A platform team manages everything. Bottleneck. Every "change my environment variable" request becomes a ticket. Developers hate it.
Option D: Internal Developer Platforms (Backstage, Port, Cortex). Powerful but heavy. Requires significant investment to build and maintain.
Score is positioning itself as a lighter alternative to Option D — a specification language that lets developers describe their workload in environment-agnostic terms, and then generates platform-specific output.
What Score Actually Is
Score is a YAML specification. That's it. A developer writes a score.yaml that describes their workload's requirements:
apiVersion: score.dev/v1b1
kind: Workload
metadata:
name: payment-service
annotations:
score.dev/description: "Handles payment processing"
spec:
containers:
main:
image: payment-service:${IMAGE_TAG}
command: ["/app/server"]
# What the container needs — not HOW to provide it
resources:
requests:
cpu: "0.5"
memory: "256Mi"
limits:
cpu: "2"
memory: "1Gi"
# Environment variables — reference to resources, not hardcoded values
variables:
DATABASE_URL: "${resources.db.connection_string}"
REDIS_URL: "${resources.cache.url}"
PORT: "8080"
# Ports the container exposes
ports:
http:
port: 8080
targetPort: 8080
metrics:
port: 9090
# What resources this workload depends on
resources:
db:
type: postgres
properties:
version: "15"
size: "small"
cache:
type: redis
properties:
maxmemory: "256mb"
dns:
type: dns
properties:
host: payment.internal
# Service dependencies
service:
ports:
http:
port: 80
targetPort: 8080Notice what's not in this file:
- No Kubernetes resource types (no Deployment, no Service, no ConfigMap)
- No environment-specific configuration (no AWS-specific settings, no cluster names)
- No secrets — only references to resources
- No ingress configuration — only a
dnsresource declaration
This score.yaml is the developer's contract: "My app needs these resources and these ports. Figure out how to provide them."
How Score Translates to Real Infrastructure
Score uses provisioners — platform-specific translators that take the score.yaml and generate actual infrastructure manifests.
Two official provisioners exist:
score-k8s — generates Kubernetes manifests:
# Install
brew install score-spec/tap/score-k8s
# Generate Kubernetes manifests
score-k8s generate score.yaml \
--output k8s-manifests/ \
--image payment-service:v1.2.3This outputs a Deployment, Service, and ConfigMap that implements what the score.yaml described.
score-compose — generates Docker Compose files for local development:
score-compose generate score.yaml \
--output docker-compose.yaml \
--image payment-service:latestThe same score.yaml produces a working Docker Compose file for local development. The developer writes one spec, gets local dev and Kubernetes production from the same source.
What Score Gets Right
The conceptual model is correct
Separating "what my app needs" from "how the platform provides it" is the right abstraction. This is the same insight behind Crossplane's Compositions and Kubernetes's PersistentVolumeClaim — the consumer declares a need, the platform fulfills it.
Score applies this to the entire workload description, not just storage. That's genuinely novel.
Local-to-production parity
The score-compose + score-k8s combination solves a real problem: developers running docker compose up locally and kubectl apply in production often have different configurations because they're maintained separately. Score gives you one source of truth.
Developer cognitive load
A developer writing score.yaml doesn't need to know what a ServiceAccount is, what topologySpreadConstraints do, or how PodAffinity works. They describe their app. The platform engineer's provisioner handles the rest.
Where Score Falls Short
The resource abstraction is underdeveloped
type: postgres in a score.yaml is nice in theory. But what does it actually provision in production? An RDS instance? A CloudNativePG cluster? An in-cluster StatefulSet? A managed Cloud SQL instance?
Score doesn't define this — it leaves it to the provisioner. Which means you need to either write your own provisioner or rely on the defaults, which are basic. In practice, this means a platform team still needs to build and maintain the provisioner logic, and developers still end up asking "what does type: postgres give me exactly?"
The ecosystem is tiny
Helm has 10,000+ charts. Helm values are supported by every Kubernetes tool in existence. Score has two official provisioners and a nascent community. If you hit an edge case — and you will — you're on your own.
No path for complex workloads
Score works well for "a container that needs a database and a cache." But real production workloads have: init containers, sidecars, custom RBAC, pod anti-affinity rules, spot instance tolerations, topology spread constraints, custom network policies...
Score can't express most of this. The spec is deliberately minimal. Which means Score becomes the entrypoint for simple services, but complex workloads still need full Helm/Kustomize treatment. Now your platform team maintains two systems.
Versioning and rollback story is unclear
Helm's versioning and rollback is well-defined. helm rollback myapp 3 is intuitive. Score doesn't address operational lifecycle management — it's a specification language, not a deployment tool. You still need something to manage rollouts, rollbacks, and history.
Who Should Use Score Today
Good fit:
- Platform teams building internal developer platforms who want a standard workload spec format
- Teams where most services are "standard" web apps with simple infrastructure needs
- Organizations investing in Platform Engineering and wanting to formalize the developer/platform contract
Not a good fit:
- Teams with complex workloads requiring fine-grained Kubernetes control
- Small teams where the overhead of building provisioners outweighs the benefit
- Anyone who needs battle-tested ecosystem support today
The Bigger Picture
Score is part of a broader movement: the recognition that Kubernetes was designed as a platform for platforms, not as a developer interface. The CNCF calls this "Platform Engineering" — building internal abstractions that make Kubernetes invisible to application developers.
Score, Crossplane, Backstage, Port, and Radius are all exploring different points in this space. Score's bet is that a simple YAML spec is the right developer interface — simpler than Backstage's full IDP, more opinionated than raw Kubernetes.
The bet might be right. The timing might be early. Watch this project — if the provisioner ecosystem develops and tooling matures, Score could become the standard way developers describe workloads across environments.
For now, it's a compelling concept with a thin implementation. Worth following, worth piloting for simple services, not yet worth betting your entire platform on.
Build and validate your Kubernetes configs: YAML Validator — check Kubernetes YAML for errors before applying.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
What is a Kubernetes CRD? Custom Resources Explained Simply (2026)
CRDs extend the Kubernetes API with your own resource types. Learn what Custom Resource Definitions are, why they exist, and how tools like ArgoCD, Cert-Manager, and Prometheus use them.
What is a Kubernetes Operator? Explained Simply (2026)
Kubernetes Operators sound complex but they solve a simple problem: automating the management of stateful applications. Here's what they are and how they work.
What is Multi-tenancy in Kubernetes Explained Simply
Multi-tenancy in Kubernetes lets multiple teams share one cluster safely. Learn namespace-based tenancy, vCluster, RBAC, network policies, and when to go single vs multi-tenant.