CONCEPT Cited by 1 source
Shift-left validation¶
Definition¶
Shift-left validation is the engineering stance of moving a correctness check earlier in a change's lifecycle — from runtime to deploy time, from deploy time to apply time, from apply time to commit time, from commit time to the developer's editor. The earlier the check fires, the cheaper it is to fix the error and the more specific the blame is: the person who wrote the mistake gets the rejection, not a downstream operator reading a vague runtime log.
The name comes from shift-left testing / security — the same move applied to tests (unit tests in CI, not manual QA in staging) and to security (SAST in the PR pipeline, not pen-test after release). See also concepts/shift-left-privacy for the privacy-specialised form.
The failure loop it targets¶
Without shift-left validation:
1. Developer writes bad manifest / config / code
2. kubectl apply / push / deploy — accepted
3. Runtime consumer chokes silently or visibly
4. Someone else notices: support channel, page, on-call
5. That someone else files a bug
6. Someone has to bisect back to step 1
7. Original developer finally hears about it, context-switched
Steps 3–7 can take hours to days. The developer who made the mistake has moved on to something else. Every step after 2 is waste: the information that would reject the change was present at step 2 but not checked.
With shift-left validation the loop collapses to:
1. Developer writes bad manifest / config / code
2. kubectl apply / push / deploy — rejected with actionable error
3. Developer fixes it in the same session
Where the line sits¶
The left-most the validation can sit is usually bounded by information availability:
- Editor / IDE: only local information (syntax, local types).
- Pre-commit hook: adds repo-wide information (cross-file refs, lint rules).
- CI: adds build artefacts (does this compile, do tests pass).
- Admission / deploy time: adds target-environment information — does the thing you're about to write make sense against the current running system (cluster-resident CRDs, namespace policies, existing service references). This is where a concepts/validating-admission-webhook lives.
- Runtime: the right edge; everything upstream failed.
The Skipper admission-webhook case sits at admission time specifically because "does this filter exist in the Skipper runtime" needs information from the running Skipper binary — not just from the manifest. It cannot be done in CI without re-hosting the Skipper filter registry there.
The cost the move pays for¶
Shift-left validation is not free:
- The check becomes a write-path blocker. A validating admission webhook that's down, slow, or over-strict freezes CI/CD fleet-wide (concepts/control-plane-change-blast-radius).
- Symmetry matters. If the shift-left check disagrees with the runtime check, the developer gets rejected at apply time for something that would have worked, or accepted at apply time for something that will fail at runtime. Both are worse than the original loop. Symmetry is why reusing the runtime validator is load-bearing — it guarantees the two answers cannot drift.
- Actionable error messages are non-negotiable. A shift-left check that rejects with "validation failed" reproduces the original loop one step earlier; the developer still has to go bisect. The Skipper webhook propagates Skipper's exact message ("predicate 'NonExistingPredicate' not found") because the fast rejection is only useful if it names the fix.
Seen in¶
- sources/2026-04-08-zalando-rejecting-invalid-ingress-routes-at-apply-time
— ingress-routing case. Before the webhook, a typo like
Headr("X-Canary", "true")in azalando.org/skipper-predicateannotation was a valid string to Kubernetes, so theIngressapplied cleanly and the broken route later surfaced in production — often to a support channel, not to the developer. After the webhook, the same typo failskubectl applywith Skipper's predicate-registry error. The 250+ cluster × 200k route scale makes the shift-left move load-bearing: "at that size, even 1% invalid routes is not background noise. It is real production risk." Implementation detail that matters: Zalando chose to reuse Skipper's own validator, not reimplement the rules in a policy engine — the correctness of the shift-left check is defined as "same answer the data plane would give." - See also concepts/jsonschema-config-validation and patterns/jsonschema-validated-config-both-local-and-ci for the JSON-Schema flavour of shift-left validation applied to CloudFormation templates at Zalando's RDS fleet.
Related¶
- concepts/validating-admission-webhook · concepts/shift-left-privacy · concepts/jsonschema-config-validation · concepts/deploy-less-operational-lever · concepts/control-plane-change-blast-radius · concepts/feature-flag-rollback-for-validator
- patterns/reuse-runtime-logic-on-admission-path · patterns/jsonschema-validated-config-both-local-and-ci · patterns/invisible-rollout-via-default-on-validation