Webinar · Oct 20: The migration takes 2 weeks. Deciding to do it takes 6 months.

OPA Gatekeeper vs Kyverno vs a Managed Platform Layer: Where Should Deployment Policy Live?

OPA Gatekeeper and Kyverno enforce deployment policy at the Kubernetes admission controller, after a bad config has already been written. A managed platform layer enforces it before the config exists. Here is how the two layers compare, where Crossplane, Backstage, Port and Argo CD actually fit, and which one to start with.

Romaric Philogene
CEO & Co-founder
OCT 9, 2026 · 13 MIN
OPA Gatekeeper vs Kyverno vs a Managed Platform Layer: Where Should Deployment Policy Live?

I have had a version of this argument with a dozen platform teams this year. Someone installs an admission controller, writes a rule that blocks pods without resource limits, flips it to deny, and the next morning three product teams cannot ship because nobody told them the rule existed or how to satisfy it. The tool worked exactly as designed. The rollout was the problem, and underneath the rollout was a layering problem.

So the honest answer to "OPA Gatekeeper, Kyverno, or a platform layer for deployment policy" is that they are not competing for the same job. OPA Gatekeeper and Kyverno are Kubernetes admission controllers: they reject bad config at the last moment before it hits the cluster. A managed platform layer enforces policy earlier, by generating the config so the bad version is never written. Most mature teams run both. This article is about where each one fits and which to start with.

Qovery · Agentic Infrastructure Platform
A control plane for platform teams and their coding agents
Learn more

Key takeaways

  • OPA Gatekeeper and Kyverno are Kubernetes admission controllers. They evaluate API server create and update requests through a validating webhook and reject non-compliant resources. That means a developer already wrote, committed, pushed, and merged the bad config before the feedback arrived.
  • A managed platform layer enforces policy by construction. An internal developer platform such as Qovery, or Port and Backstage plus pipelines you build, generates the manifests, so privileged pods, missing resource limits, unapproved registries, and deploys to the wrong cloud account are never authored in the first place.
  • Gatekeeper and Kyverno cannot enforce anything outside the Kubernetes API server. Cloud IAM, which AWS, GCP, Azure, or Scaleway account an environment lands in, managed database backup settings, and who may deploy to production are all out of scope for an admission webhook.
  • Choose by language and scope. Pick OPA Gatekeeper if you need Rego and one policy language across Kubernetes, Terraform, CI, and service authorization. Pick Kyverno if you are Kubernetes-only and want YAML policies with no Rego learning curve. Both are CNCF graduated projects with an audit-first mode.
  • The mature stack uses every layer. A platform layer for golden paths, Kyverno or Gatekeeper as the cluster-wide backstop, Argo CD for delivery, and OPA in CI for Terraform plans. A platform layer does not replace an admission controller, and an admission controller does not create a golden path.

OPA Gatekeeper vs Kyverno vs a managed platform layer: which should enforce deployment policy?

Run two layers, because they enforce at different moments in the lifecycle. A managed platform layer enforces by construction, so developers can only produce compliant config because the platform generates it. OPA Gatekeeper and Kyverno enforce by rejection at the Kubernetes admission controller, the last possible moment before a resource is persisted. If you can only deploy one layer this quarter, pick by failure mode: an admission controller when your risk is unknown config reaching the cluster from any source, a platform layer when your risk is developers hand-writing YAML they do not fully understand.

The terms get used loosely, so here is each one in a single sentence. OPA (Open Policy Agent) is a general-purpose policy engine that evaluates rules written in a language called Rego. OPA Gatekeeper is a Kubernetes validating and mutating admission webhook that runs OPA plus a Constraint Framework. Kyverno is a Kubernetes-native admission webhook whose policies are written in plain YAML. A managed platform layer is the system that generates deployment config from templates and owns an opinionated deploy API, so compliance is a property of the output rather than a check on it.

Policy can be enforced at five points in a change's life, and each tool owns a different one. The table below maps them in order.

Enforcement momentWho owns itWhat it can stop
Template / generationA managed platform layer (Qovery, or Backstage/Port + your pipelines)The violation is never authored: no privileged: true, no missing limits, no unapproved registry
Pull request / CIOPA in CI, the gator CLI, the kyverno CLIA bad manifest or Terraform plan, surfaced in the PR before merge
GitOps syncArgo CD (AppProjects, RBAC)An unauthorized source, path, or destination syncing to the cluster
Admission webhookOPA Gatekeeper, Kyverno, Pod Security AdmissionAny non-compliant resource reaching the API server, from any source
RuntimeRuntime security tooling (out of scope here)Behavior after the pod is already running

I want to say this plainly and early: OPA Gatekeeper and Kyverno are both good, and this is not an argument against either. OPA is a CNCF graduated project and Gatekeeper is the reference admission implementation for Kubernetes. The uncomfortable part is just that admission control is a backstop, not a developer experience. A rejection is feedback that arrives after the work is done and after the pull request has been reviewed. That is fine for a backstop and painful as a primary workflow.

What does OPA Gatekeeper actually enforce, and where does it stop?

OPA Gatekeeper enforces policy on Kubernetes API server requests and nothing else. It intercepts create, update, and optionally delete calls through a validating admission webhook, evaluates Rego constraints defined as ConstraintTemplate and Constraint custom resources, and admits or rejects the request. Terraform plans, CI pipelines, cloud IAM, managed database settings, and which cloud account an environment lands in are all outside its reach unless you run OPA separately in those places.

The mechanics are worth getting right. You write a ConstraintTemplate (the reusable Rego logic), then create Constraint resources that apply it with parameters. An audit controller continuously re-evaluates resources that already exist, so you find violations that predate the policy. The enforcementAction field takes deny, dryrun, or warn, which is what lets you roll out in audit mode before you block anything.

The real strengths: a cluster-wide guarantee regardless of who applied the manifest (kubectl, Helm, Argo CD, a forgotten CI job), continuous audit of existing resources, mutation to inject safe defaults, and the gator CLI to test constraints in CI before they ever reach a cluster.

The honest limits: Rego has a genuine learning curve, the webhook adds latency and an availability dependency, there is no native enforcement of cloud resources, and policy sprawl is real once you run many clusters. The availability point is not theoretical. A Kubernetes admission webhook has a default timeoutSeconds of 10, and with failurePolicy: Fail the API server rejects requests when the webhook is unreachable. An unhealthy webhook pod can therefore turn into a cluster nobody can deploy to.

Why did so many teams end up installing one of these at all? Because PodSecurityPolicy was deprecated in Kubernetes v1.21 and removed in v1.25, which left teams choosing between the built-in Pod Security Admission, Gatekeeper, or Kyverno for anything beyond the basics. The single strongest reason to pick OPA over Kyverno is reach: the same engine and language evaluate Terraform plans, Envoy external authorization, CI checks, and your own application APIs.

How is Kyverno different from OPA Gatekeeper for Kubernetes policy?

Kyverno writes policies as Kubernetes YAML resources and is Kubernetes-only by design, so a small platform team can ship useful policies in a day without learning a new language. OPA Gatekeeper writes policies in Rego, which takes longer to learn but lets you reuse one engine across Kubernetes, Terraform plans, CI, and service authorization. Both are CNCF graduated projects, both run as admission webhooks, and both support an audit-first rollout.

Kyverno can do a few things Gatekeeper cannot do natively. Its generate rules auto-create resources like NetworkPolicies, ResourceQuotas, and Secrets in new namespaces, and its verifyImages rules check container image signatures through Sigstore and cosign. Gatekeeper's edge runs the other way: the Constraint Framework, the gator CLI for shift-left testing, a large library of prebuilt constraint templates, and Rego you can reuse outside Kubernetes.

A maturity note for 2026, because it changed recently: Kyverno moved to CNCF incubating in July 2022 and graduated in March 2026. Both projects are now top-level CNCF, so "graduated vs incubating" is no longer a differentiator between them.

OPA GatekeeperKyverno
Policy languageRego (ConstraintTemplate + Constraint)Kubernetes YAML
ScopeMulti-domain (K8s, Terraform, CI, authz) via OPAKubernetes-only by design
ValidationYesYes
MutationYesYes
Resource generationNo native equivalentYes (generate rules)
Image signature verificationVia external OPA integrationNative (verifyImages, Sigstore/cosign)
Shift-left CLIgatorkyverno CLI (test)
Audit-mode flagenforcementAction: dryrunvalidationFailureAction: Audit
Learning curveHigher (Rego)Lower (YAML)
CNCF maturityGraduated (OPA, Feb 2021)Graduated (Mar 2026)
GitHub stars (obs. 2026-10-09)~4.3k (gatekeeper), ~12.3k (OPA)~8.2k

The selection rule I give teams: if a security or policy team already writes Rego, pick Gatekeeper and reuse it everywhere. If a one-to-three-person platform team owns Kubernetes and nothing else, pick Kyverno and skip Rego entirely.

Do Crossplane, Backstage, Port, or Argo CD enforce deployment policy?

None of these four is a policy engine, and treating one as a substitute for an admission controller is the most common architectural mistake in this space. Crossplane constrains the shape of infrastructure that can be provisioned. Backstage and Port constrain what a developer can request. Argo CD constrains how a change reaches the cluster. The allow-or-deny decision on an individual Kubernetes resource still needs an admission controller, or a platform that owns manifest generation outright.

Crossplane exposes cloud resources through Compositions and CompositeResourceDefinitions. That is a guardrail on your API surface, which is policy by what you choose to expose, not policy by evaluation. Crossplane is a CNCF incubating project, and most teams running it still run Gatekeeper or Kyverno on the control plane cluster itself.

Backstage is a developer portal and software catalog donated to the CNCF by Spotify. Its Scaffolder templates create golden paths at project creation time, but Backstage enforces nothing at deploy time, and it is a framework your team builds, hosts, and maintains. The DIY cost is real and ongoing: plugins, templates, and the portal itself are software you now own.

Port is a hosted internal developer portal with self-service actions and scorecards. Scorecards measure and nudge compliance. The actual execution is delegated to your own pipelines, which is exactly where enforcement still has to be implemented.

Argo CD guarantees the cluster matches Git and controls who may sync what through AppProjects and RBAC. That is a delivery guarantee, not a content guarantee. A perfectly compliant sync of a non-compliant manifest still ships the violation.

Worth naming as the free floor beneath all of this: Kubernetes Pod Security Admission, stable and enabled by default since v1.25. It enforces the Pod Security Standards privileged, baseline, and restricted profiles at the namespace level, and nothing else. The gap every one of these shares is the same: a human still authors the Kubernetes or Terraform config, so you still need either rejection at admission or generation by a platform.

Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.

What can a managed platform layer enforce that an admission controller cannot?

A managed platform layer enforces policy before any config exists, and it enforces past the cluster boundary. Because it owns manifest generation, cluster lifecycle, environment topology, RBAC scoping, and cloud resource provisioning, violations such as privileged: true, missing resource limits, an unapproved image registry, or a production deploy by the wrong team become structurally unavailable rather than merely rejected. An admission controller can only say no to something a human already wrote, inside one cluster.

Policy by construction is the whole point. If the platform generates the Deployment, nobody sets privileged: true, nobody forgets CPU and memory limits, and nobody pulls from an unapproved registry. Those are the two categories, missing limits and over-permissive security contexts, that dominate almost every audit inventory and show up repeatedly in Datadog's container usage reports. You cannot violate a field the platform fills in for you.

The scope also runs past the API server, which is where admission control simply cannot reach: which cloud account and region an environment lands in, who can deploy to production, which database engine and backup policy is used, and auto-stop rules for non-production environments. And the feedback is instant, because the compliant path is the default path. Developers never see a rejection for the classes of policy the platform owns, which removes a whole category of unplanned work.

This is where Qovery fits. Qovery is a cloud-agnostic, Kubernetes-native internal developer platform that runs inside your own AWS, GCP, Azure, or Scaleway account, or on your existing Kubernetes cluster. Because it is deployed in your own account (BYOC), the cloud bill, any Savings Plans or committed-use discounts, and your data stay in your name. The capabilities I will stand behind: git-push deployments, preview and ephemeral environments per pull request, environment auto-stop for non-production, managed cluster upgrades, per-environment RBAC, and databases backed by managed cloud services.

Here is the fair trade-off. A platform layer is opinionated, so highly bespoke workloads will hit its edges, and anything deployed outside the platform is unenforced. That last point is exactly why you keep Kyverno or Gatekeeper running as the cluster-wide backstop. To be explicit about what Qovery is not: it does not ship a Rego engine, it is not an admission controller, and it does not replace one. It removes the need for a rejection by making the compliant manifest the only one that gets generated, and you keep the admission controller for everything the platform does not generate.

LayerWhere enforcement happensWhat it can blockWhen the developer gets feedbackCovers cloud resources outside the cluster?Who builds and maintains itPolicy language
OPA GatekeeperAdmission webhookAny non-compliant K8s resourceAt apply/deploy (after authoring)NoYou (constraints)Rego
KyvernoAdmission webhookAny non-compliant K8s resourceAt apply/deploy (after authoring)NoYou (policies)YAML
CrossplaneProvisioning API surfaceInfra shapes you did not exposeAt provisioning requestYes, for infra it managesYou (Compositions)YAML/CRDs
Backstage / PortRequest / scaffolding timeWhat a developer may requestAt project creation (not deploy)Indirectly, via your pipelinesYou (portal + pipelines)Config + your code
Argo CDGitOps syncUnauthorized sync source/targetAt syncNoYou (AppProjects/RBAC)YAML
QoveryManifest generationViolations never authoredInstant (compliant by default)Yes (account, RBAC, DB, auto-stop)Managed platformNone (generated config)

The hybrid architecture most mature teams converge on is short: a platform layer for golden paths, Kyverno or Gatekeeper for the cluster-wide guarantee, Argo CD for delivery, and OPA in CI for Terraform plans.

How do you roll policy enforcement out across many teams without blocking everyone?

Run audit mode first, publish the violation inventory, ship the compliant default path, then flip policies to deny one at a time. Policy enforcement without a golden path does not create compliance. It moves unplanned work onto developers who never asked for it, and the rejection rate becomes the metric that tells you the golden path is missing.

The sequence that works:

  1. Inventory before you enforce. Run Gatekeeper audit (enforcementAction: dryrun) or Kyverno Audit mode to count existing violations, and publish the count per team.
  2. Test policies in CI. Surface failures in pull requests instead of at deploy time, using the gator CLI for Gatekeeper or the kyverno CLI test command for Kyverno.
  3. Publish the compliant path on day one. Ship the template or platform golden path the same day you announce the policy, never afterward.
  4. Make exemptions explicit. Scope them per namespace with an owner and an expiry date, rather than hiding them behind a blanket failurePolicy: Ignore.
  5. Measure the right things. Track violation count, time to first successful deploy for a new service, and developer rejection rate. A rising rejection rate means the golden path is wrong, not that developers are careless.

Two warnings from watching this go badly. First, the webhook availability trap: a default timeoutSeconds of 10, plus failurePolicy: Fail, plus an unhealthy webhook pod equals a cluster nobody can deploy to. Second, the two violations that dominate every inventory are missing resource limits and over-permissive security contexts. Misconfiguration, not novel exploits, is what Red Hat's State of Kubernetes Security research keeps pointing to as the leading source of container and Kubernetes security incidents. Both of those are generation problems, which is the strongest practical argument for a golden path sitting in front of the admission controller.

Which policy enforcement stack should your team choose in 2026?

Pick by what you are actually protecting against and by how many platform engineers you have, not by GitHub stars. Platform engineering is mainstream now: Gartner has projected that 80% of large software engineering organizations will have platform teams by 2026, up from 45% in 2022. Four team profiles cover most situations.

Team profileRecommended stackSetup effortPrimary risk it leaves open
Regulated enterprise with a security/policy team and Terraform + CI needsOPA and Gatekeeper everywhere, one language across domains, gator in CIHighRego skill concentration; webhook availability
Small Kubernetes-only platform team (1-3 engineers)Kyverno in Audit then Enforce, plus Argo CDLow to mediumNo golden path, so developers still author YAML
Many product teams, few platform engineersA managed platform layer (Qovery, or Port/Backstage + pipelines), with Kyverno as the cluster backstopLow (managed) to high (DIY)Bespoke workloads hitting platform edges
Heavy multi-cloud infra provisioningCrossplane Compositions for the API surface, plus Gatekeeper on the control plane clusterHighInfra control plane availability; still need admission

If you are starting from zero today, the default is this: Kyverno in audit mode plus a golden path that generates compliant config, and reserve Gatekeeper for when you already need Rego outside Kubernetes. Start with the layer that matches your biggest risk, keep an admission controller as the backstop no matter what, and add the others as the team grows.

FAQ

Is OPA Gatekeeper better than a managed platform layer for enforcing deployment policy?

Neither is strictly better, because they enforce at different moments. OPA Gatekeeper rejects non-compliant Kubernetes resources at the admission webhook, after a developer has already written the config. A managed platform layer like Qovery generates the config so the violation is never authored, and it covers cloud resources outside the cluster that Gatekeeper cannot touch. Most mature teams run a platform layer for the golden path and keep Gatekeeper or Kyverno as the cluster-wide backstop.

Can an internal developer platform replace OPA Gatekeeper or Kyverno?

No, and you should not try to make it. An internal developer platform such as Qovery enforces policy by generating compliant manifests, but it only governs workloads deployed through the platform. OPA Gatekeeper and Kyverno enforce on every request to the Kubernetes API server, including kubectl, Helm, and jobs that bypass the platform. Keep an admission controller running as the backstop for anything the platform does not generate.

What is the difference between OPA, OPA Gatekeeper, and Kyverno?

OPA (Open Policy Agent) is a general-purpose policy engine that evaluates rules in the Rego language across many systems. OPA Gatekeeper is a Kubernetes admission webhook that runs OPA plus a Constraint Framework, so you can enforce Rego policies on cluster resources. Kyverno is a separate Kubernetes-native admission webhook whose policies are written in YAML instead of Rego, and it is Kubernetes-only by design.

Do Backstage, Port, or Crossplane enforce deployment policy?

No, none of the three is a policy engine. Backstage and Port are developer portals that constrain what a developer can request through templates and self-service actions, but they enforce nothing at deploy time. Crossplane constrains the shape of infrastructure you can provision through Compositions, which is a guardrail on your API surface rather than per-resource evaluation. You still need an admission controller or platform-level manifest generation for the actual allow-or-deny decision.

Does Argo CD enforce policy, or do I still need an admission controller?

Argo CD enforces delivery, not content, so you still need an admission controller. Argo CD guarantees the cluster matches Git and controls who may sync what through AppProjects and RBAC. A perfectly authorized sync of a non-compliant manifest still ships the violation, because Argo CD does not evaluate the contents of the resource. Pair it with Kyverno or OPA Gatekeeper to reject the non-compliant resource at admission.

Can OPA Gatekeeper enforce policy on cloud resources outside Kubernetes?

OPA Gatekeeper itself cannot, because it only intercepts Kubernetes API server requests. OPA, the engine underneath Gatekeeper, can evaluate Terraform plans, CI pipelines, and service authorization when you run it separately in those places. So if you want one policy language across Kubernetes and cloud infrastructure, you adopt OPA broadly and use Gatekeeper as its Kubernetes admission component, not Gatekeeper alone.

How does Qovery enforce deployment policy across teams and clouds?

Qovery enforces policy by construction: it generates deployment manifests and provisions infrastructure from an opinionated API, so privileged pods, missing resource limits, and unapproved registries are never authored. It is cloud-agnostic and Kubernetes-native, running inside your own AWS, GCP, Azure, or Scaleway account or your existing Kubernetes cluster (BYOC), and it enforces things an admission controller cannot, such as which cloud account an environment lands in, per-environment RBAC, and auto-stop for non-production. Qovery does not ship a Rego engine or an admission controller, so you keep Kyverno or Gatekeeper as the cluster-wide backstop.

Romaric Philogene
About the author
Romaric Philogene

Romaric founded Qovery to make Kubernetes accessible to every engineering team. He writes about platform strategy, developer experience, and the future of cloud infrastructure.

Next step

Ship faster on infrastructure you control.

Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.