A developer needs a database. She files a Jira ticket. Ops reads it on Tuesday, hand-writes the YAML on Wednesday, applies it Thursday — and on Friday she reports a typo in the config, so the cycle starts over. Three days, two teams, one typo. Now the same request: she runs kubectl apply -f my-database.yaml, a pipeline validates, hardens, and provisions it, and the database is running in 30 seconds. No ticket, no wait, no typo round-trip.
That contrast is the opening of Sergei Olshanetski's July 29, 2026 hands-on, "I Replaced Our Entire Ticketing System With 4 Lines of YAML," built on Syntasso's Kratix with a demo repo to prove it. His claim is not that YAML is magic — it is that a platform team can package everything it used to do by hand into a self-service Kubernetes API called a Promise, and that developers will happily consume it. Here is the verdict up front; the receipts for every line follow below.
- Promises buy ticket-free self-service without writing Go operators: a database, a microservice, or a whole app stack becomes one custom API backed by pipeline containers, not a controller you maintain.
- They cost a second control plane to run, plus real work vetting marketplace pipelines before they touch your clusters.
- SKE v0.45.0 (April 17, 2026) closed the biggest operational gap: Promise and Resource workflows can now retry through a Workflow Control file, with retry states visible in
status.kratixinstead of failing silently. - Compound Promises are the feature that makes "app stack as one API" real: one request fans out into a service, its database, and its ingress — composition without writing a line of Go.
- The complexity threshold is concrete: one or two services, and Helm plus scripts still win; around four ticketed services with teams queuing on ops, and promises pay back.
- For a Cluster API fleet, the first promises worth building are the tenant primitives you already hand out by hand: preview environments and per-tenant quotas.
What a Promise actually is, in 60 seconds
A Promise is a contract between the platform team and everyone else, expressed as a Kubernetes API. The platform team defines two things: the API schema (what a developer is allowed to ask for — service name, port, team, environment) and a set of pipelines (container jobs that turn a request into running infrastructure).
A developer sends a Resource request — plain YAML against that API. Kratix runs the configure pipeline, which validates the request, applies hardening (security contexts, labels, resource limits), generates the real manifests, and writes them to a Destination through a StateStore (a Git repo or an S3-compatible bucket like MinIO). A delete pipeline cleans everything up when the request disappears.
The shape of a request is deliberately boring:
apiVersion: platform.example.io/v1alpha1
kind: Database
metadata:
name: scoreboard-db
namespace: team-nba
spec:
engine: postgres
size: small
team: stats-serviceFour meaningful lines under spec, which is where the hands-on's title comes from. Installing a Promise is equally boring: one kubectl apply of the Promise definition, often straight from the community marketplace (promise-postgresql, Jenkins, Redis, vcluster, app-as-a-service). That one apply extends the platform cluster with a new API — kubectl get promises shows it, kubectl get crds -l kratix.io/promise-name shows the CRDs it created. From then on, fulfilling that class of request is pipeline execution, not human labor.
The demo that backs the ticketing claim runs on a laptop: a Minikube profile on Kubernetes v1.32.0, Kratix installed with Helm, MinIO as the StateStore, the same cluster registered as a Destination. Three NBA microservices play the tenants.
Three promises serve them: an NBA Service promise ("I need a new microservice," with a configure pipeline emitting a Deployment plus Service plus ConfigMap and a delete pipeline for teardown), a PostgreSQL promise ("I need a database"), and a Compound promise ("I need a service with its database"). Pipelines automatically inject what humans forget — security contexts, team labels, resource limits — which is exactly the category of mistake that used to bounce back as a Friday typo ticket.
What SKE v0.45.0 changed, and why it matters more than it sounds
Kratix itself is open source; Syntasso Kratix Enterprise (SKE) is the supported distribution with a built-in Backstage portal. Two spring 2026 releases changed what promises can be trusted with. On April 9, the workflow-controls announcement added Promise Pipeline Waits and Events: pipelines can now wait on real-world asynchronous conditions — an approval, a DNS record, a change ticket closing — instead of burning idle pods or relying on fragile sleep-and-poll shell scripts. The enterprise side extends this into the tools approvals actually live in: Jira, ServiceNow, Slack.
Then v0.45.0 landed on April 17 with the piece operators had been asking for in the open (upstream issue #862: failed Promise workflows sat in a failed state and were skipped by reconciliation, so nothing ever retried them on its own):
| Before v0.45.0 | After v0.45.0 | |
|---|---|---|
| Failed Promise/Resource workflow | Stuck failed until a human retriggered it | Retries through an optional Workflow Control file |
| Failure visibility | Dig through pipeline Job logs | Detailed retry states in status.kratix on the Promise and the Request |
| Async steps (approvals, DNS, tickets) | Sleep-and-poll scripts or idle pods | Pipeline Waits and Events |
| Promise admission control | Broad webhook behavior | Label selectors for the Promise webhook |
This is the release that moved promises from "great demo" to "runnable in production." A self-service API that wedges on the first transient failure — a registry hiccup, a quota race, a cloud API throttle — is worse than a ticket queue, because it teaches developers the platform cannot be trusted. Retries plus visible state are the minimum contract for anything developers are supposed to depend on without paging the platform team.
Note the honest boundary the project still debates: per-Promise reconciliation intervals retry flat with no backoff, so the floor is aggressive against an already-throttling API, and a configured maximum-retry ceiling (upstream issue #680) is still the enforcement mechanism to watch. Retries exist; retry policy is where the next release cycle goes.
Compound Promises, worked on a fleet primitive
Simple promises replace tickets for single things. Compound Promises replace tickets for stacks — and stacks are what a fleet actually hands out. A Compound Promise's workflow does not emit manifests directly; it emits sub-requests against other promises, which Kratix then fulfills independently. The canonical guide example is an AppStack: one request produces a Postgres sub-request plus Ingress rules from the NGINX Ingress Controller, with the sub-promises declared as requirements so the compound cannot install without them.
Map that onto the two tenant primitives a Cluster API fleet operator recognizes immediately.
A preview-environment promise takes explicit inputs — branch or image tag, database engine and size, a TTL in hours — and fans out into a namespace, a Postgres sub-request sized for disposable data, and Ingress rules with the PR hostname. One developer request, three lifecycled objects, automatic teardown when the TTL expires. This is the workload that otherwise costs either a pre-warmed pool sitting idle or a human provisioning per-PR namespaces by hand.
A per-tenant quota promise is the case that shows why composition must be a primitive rather than documentation. A quota is never one object: it is a ResourceQuota plus a LimitRange plus cost-center labels, and the three share exactly one lifecycle — create them together, version them together, delete them together. As a compound promise, that lifecycle is enforced by the platform. As three kubectl applies in a runbook, it drifts the week someone applies two of them.
The hands-on demo's Compound promise ("a service with its database") is the small version of this same pattern, and its failure drills are the honest part most tutorials skip: a broken pipeline image, a missing Destination, an invalid request. Each fails in the open with the retry states v0.45.0 added, which is the only reason the demo's 30-second claim survives contact with reality.
The honest cost ledger
Nothing here is free. A team deciding between promises and hand-rolled operators should price both sides:
| Cost | Promise model | Hand-rolled Go operator |
|---|---|---|
| New control plane | Yes — Kratix controllers, StateStores, Destinations to run and upgrade | No — but you own every line of reconciliation |
| Fulfillment logic | Pipeline containers (shell, Python, Terraform, Helm — skills the team has) | Go + controller-runtime + kubebuilder scaffolding (a smaller hiring pool) |
| Failure handling | Workflow Control retries + Waits/Events, improving since April 2026 | Whatever you build, including the retry bugs you will write first |
| Community content | Marketplace promises exist but must be vetted and hardened before they touch your clusters | N/A — everything is bespoke, which is itself the cost |
| API evolution | Schema change on the Promise, old requests keep reconciling | CRD versioning and conversion webhooks you maintain |
Two clarifications the ecosystem gets wrong. First, Kratix versus Crossplane is not a rivalry: both expose declarative facades (Promises versus Compositions), but Kratix orchestrates platform workflows across destinations while Crossplane orchestrates cloud resources — Syntasso's own docs ship a Crossplane Promise because the intended shape is composition, not replacement.
Second, the Backstage pairing is load-bearing, not decorative: SKE auto-populates the Backstage catalog with Components and Templates per Promise, so "self-service" means a button in the portal developers already open, not a CRD reference they must memorize. The CNCF "Composable Platforms" talk (Salahi and Brundke) demonstrates exactly this integrated shape. A promise nobody can discover is a ticket queue with extra steps.
The threshold: when promises beat shell scripts
The decision table, grounded in the hands-on evidence:
| Team shape | Right answer | Why |
|---|---|---|
| One service, one developer, no tickets | Helm chart + scripts | A promise's control plane costs more than the toil it removes |
| Two or three services, occasional ops help | Scripts + marketplace promises for the annoying one (databases first) | Adopt selectively; vet one pipeline, not a platform |
| Four-plus services with teams queuing on ops tickets | Promise model | Ticket-queue depth times wait time now exceeds promise-authoring days; the demo's three-promise Minikube setup is the shape of the proof |
| Fleet with tenant primitives (preview envs, quotas, per-team stacks) | Compound promises as the default way new primitives ship | Shared lifecycle across objects is the requirement scripts cannot meet |
The rule of thumb: count the tickets your platform team closes per week that are structurally identical — another database, another namespace, another preview env. When that count sustains one engineer's part-time attention, you have already paid for the promise; you are just paying for it in latency instead of in YAML. The July hands-on marks the crossing point empirically: three promises, three microservices, twenty minutes from zero to self-service on a laptop, ticket queue deleted.
There is a counter-argument worth steel-manning: promises add a control plane, and control planes fail in ways scripts do not. True — and the correct response is the v0.45.0 test: can the platform's own failure modes (wedged workflow, missing destination, invalid request) surface visibly and recover without a human? Before April 2026 the answer was shaky; after retries plus visible states plus Waits/Events, it is good enough to bet a preview environment on, with production databases following once retry policy matures.
What this means for your next primitive
The direction of travel is visible across the ecosystem: CNCF's Q1 2026 radar put kro, the declarative CRD-composition project, in the Adopt ring next to Helm and Backstage — the same lineage as promises, replacing hand-written operators with composed APIs. Kratix's bet is that the composition layer should be a product surface (catalog, portal buttons, retry states a developer can read) rather than an operator SDK exercise.
For a team running its own fleet, the practical move is small: install Kratix on a dev cluster, publish one marketplace Postgres promise, vet its pipeline line by line, and measure how many tickets stop arriving. Then write the preview-environment promise — the compound one — because that is the primitive whose lifecycle your scripts are already failing to hold together.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



