Vault Secrets Operator vs External Secrets Operator: Which One Should You Run?
Both VSO and ESO sync secrets into Kubernetes — but they make completely different assumptions about your infrastructure. Here's how to pick the right one without regretting it six months later.

Both Vault Secrets Operator and External Secrets Operator solve the same surface-level problem: getting secrets out of an external store and into Kubernetes. But they make completely different assumptions about what "external" means, how tightly coupled your secrets architecture should be to your infrastructure choices, and who owns the rotation lifecycle.
Pick the wrong one and you'll either lock yourself into a single vendor at exactly the wrong moment, or add an abstraction layer you don't need and will spend the next year debugging.
I've deployed both in production. Here's the honest comparison.
What Each Operator Actually Does
Vault Secrets Operator (VSO) is HashiCorp's official Kubernetes operator for syncing secrets from Vault into native Kubernetes Secrets. It's Vault-native — meaning it talks directly to Vault's API, understands Vault's auth methods (AppRole, Kubernetes, JWT), and exposes Vault-specific CRDs. It replaced the older Vault Agent Sidecar Injector pattern for teams that want operator-based syncing instead of per-pod sidecars.
External Secrets Operator (ESO) is a CNCF sandbox project that provides a provider-agnostic abstraction over dozens of secret backends: AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, HashiCorp Vault, 1Password, Doppler, and more. It defines a uniform set of CRDs regardless of which backend you use.
Both create native Kubernetes Secret resources in your cluster. Both use controller reconciliation loops to keep those secrets in sync. The difference is in what they talk to and how much flexibility they trade for that capability.
Architecture Comparison
Vault Secrets Operator
VSO introduces three primary CRDs:
- VaultStaticSecret — syncs a KV secret from Vault into a Kubernetes Secret on a polling interval
- VaultDynamicSecret — creates and renews dynamic credentials (database passwords, AWS access keys generated via Vault's dynamic secrets engine)
- VaultPKISecret — manages certificate lifecycle via Vault's PKI secrets engine
Each resource references a VaultConnection (where to find Vault) and a VaultAuth (how to authenticate). VSO handles token renewal automatically, rotating secrets in-cluster when Vault TTLs expire.
The critical architectural point: VSO is aware of Vault's internal concepts. It understands leases. It knows how to renew dynamic credentials before they expire. It can trigger a rolling restart of dependent Deployments when a secret is rotated.
1apiVersion: secrets.hashicorp.com/v1beta1
2kind: VaultStaticSecret
3metadata:
4 name: db-credentials
5spec:
6 vaultAuthRef: vault-auth
7 mount: kv-v2
8 path: production/db
9 destination:
10 name: db-secret
11 create: true
12 refreshAfter: 1h
13 rolloutRestartTargets:
14 - kind: Deployment
15 name: api-serverExternal Secrets Operator
ESO introduces a two-layer abstraction:
- SecretStore (or ClusterSecretStore) — defines the connection to the backend provider, scoped to a namespace or cluster-wide
- ExternalSecret (or ClusterExternalSecret) — defines which secrets to sync and how to map them into Kubernetes Secrets
1apiVersion: external-secrets.io/v1beta1
2kind: SecretStore
3metadata:
4 name: aws-secretsmanager
5 namespace: production
6spec:
7 provider:
8 aws:
9 service: SecretsManager
10 region: us-east-1
11 auth:
12 jwt:
13 serviceAccountRef:
14 name: external-secrets-sa
15---
16apiVersion: external-secrets.io/v1beta1
17kind: ExternalSecret
18metadata:
19 name: db-credentials
20 namespace: production
21spec:
22 refreshInterval: 1h
23 secretStoreRef:
24 name: aws-secretsmanager
25 kind: SecretStore
26 target:
27 name: db-secret
28 creationPolicy: Owner
29 data:
30 - secretKey: password
31 remoteRef:
32 key: production/db
33 property: passwordESO's abstraction means you can swap AWS Secrets Manager for Vault (or vice versa) by changing the SecretStore definition without touching the ExternalSecret resources or your application manifests. That portability has real value — but it also means ESO doesn't understand Vault-specific concepts like dynamic secrets or PKI certificate renewal. For those, you need provider-specific workarounds.
The Decision Matrix
Use VSO when:
You're fully committed to Vault as your secrets plane. VSO is the right choice if Vault is your organisation's canonical secrets store and you have no plans to migrate. It's tighter, more efficient, and exposes Vault's full capabilities — dynamic secrets, PKI, transit encryption — directly to Kubernetes workloads without an abstraction layer.
You need dynamic secrets. ESO cannot handle Vault dynamic secrets natively. If you're using Vault's database secrets engine to generate time-limited, per-service credentials, VSO is the only operator that manages the full lifecycle: creation, renewal, and revocation.
You need certificate management via Vault PKI. The VaultPKISecret CRD handles certificate issuance and rotation end-to-end. ESO has no equivalent.
Your team already operates Vault at scale. If you have Vault running, have Vault policies written, and your on-call engineers understand Vault's auth model, VSO adds minimal operational overhead. ESO adds a new abstraction without adding capability.
Use ESO when:
Your secrets are spread across multiple backends. If you have secrets in AWS Secrets Manager, Azure Key Vault, and maybe a self-hosted Vault instance, ESO's uniform CRD layer is genuinely valuable. You write one type of manifest regardless of where the secret lives.
You're on a managed cloud with a native secrets service. If you're running EKS and already using AWS Secrets Manager, there is no reason to run Vault. ESO + AWS Secrets Manager with IRSA is simpler, cheaper, and has fewer moving parts than running Vault Enterprise or HCP Vault.
You're migrating between secret backends. ESO makes it practical to run two SecretStore backends simultaneously during a migration. You can route secrets to the new backend gradually without changing application manifests.
You're avoiding Vault operational overhead. Running Vault in HA mode with auto-unseal, audit logging, and backup is non-trivial. If your team doesn't have that capacity, ESO with a managed secrets service is the right trade-off.
Where Both Operators Fall Short
ESO with Vault doesn't support dynamic secrets. This is ESO's biggest gap. If you're using Vault for anything beyond KV secrets — database credentials, AWS STS tokens, SSH CAs, PKI — ESO can't manage those workflows. You'd need to layer in additional tooling.
VSO doesn't support multi-provider. If you need a secret from AWS Secrets Manager in one namespace and from Vault in another, VSO can't help with the AWS side. You'd end up running both operators, which defeats the purpose of choosing one.
Neither operator eliminates the Kubernetes Secret problem. Both ultimately materialise secrets as native Kubernetes Secret objects, which are base64-encoded and accessible to anyone with kubectl get secret in that namespace. If you don't have etcd encryption at rest and tight RBAC, both operators give you a false sense of security. The operator solves the injection problem, not the access control problem.
Rotation propagation is operator-specific. Both operators support rolling restarts on secret rotation via annotations or CRD fields, but the implementations differ. VSO's rolloutRestartTargets is more explicit. ESO uses annotations on the target Secret. Neither handles stateful workloads (databases, message queues) that need application-level reconnection logic — you still need to implement that yourself.
Production Checklist
Regardless of which operator you choose:
- Enable etcd encryption at rest — operators sync secrets into
Secretobjects, which are only as secure as your etcd - Scope RBAC tightly — your operator's service account needs the minimum Vault/Secrets Manager permissions for its tasks only
- Monitor secret sync failures — both operators emit metrics; set alerts on
ExternalSecretorVaultStaticSecreterror conditions - Test rotation — verify that pods actually pick up rotated secrets; don't assume rollout restart works until you've tested it
- Audit trail — Vault's audit log or AWS CloudTrail should record every secret read; if it doesn't, your compliance posture is weaker than you think
My Recommendation
If you're already running Vault and need dynamic secrets or PKI: VSO. Don't add ESO's abstraction layer if you're not going to use its multi-provider capability.
If you're on AWS EKS, using AWS Secrets Manager, or managing secrets across multiple backends: ESO. It's simpler to operate, has a large community, and doesn't require you to run another service.
If you're undecided: start with ESO. It's more forgiving to grow out of than VSO, because you can always add a Vault SecretStore later without rewriting your ExternalSecret manifests.
The one combination I'd avoid: running both operators to cover different namespaces. It creates confusion about which secrets are managed where and doubles your operator operational surface.
For the broader question of whether to use Vault, ESO, or SOPS, see Secrets Management in Kubernetes: Vault vs ESO vs SOPS.
Frequently Asked Questions
Can I run VSO and ESO simultaneously in the same cluster?
Yes, and some teams do — VSO for namespaces where dynamic secrets or PKI are needed, ESO for everything else. The operators don't conflict. The cost is operational complexity: your team needs to understand both CRD surfaces, and debugging secret sync failures requires knowing which operator owns which secret.
Does ESO support HashiCorp Vault?
Yes. ESO has a Vault provider that supports KV v1, KV v2, and PKI secrets engines for static secret syncing. It does not support Vault dynamic secrets (database, AWS, SSH engines). For those, you need VSO or the Vault Agent Sidecar Injector.
Is VSO production-ready?
VSO reached GA in 2023 and is actively maintained by HashiCorp. It's production-ready for teams running Vault. The main consideration is that it ties your Kubernetes secrets lifecycle to HashiCorp's release cadence and licensing decisions — relevant context given HashiCorp's 2023 BSL license change for Vault.
What happens if the operator goes down?
Existing Kubernetes Secret objects remain intact — pods already running don't lose access to secrets they've already loaded. New pods that need secrets will fail if the operator isn't available to create the Secret. This is why operator HA (multiple replicas, proper resource limits) matters in production.
Does ESO handle secret rotation automatically?
ESO polls the backend on the refreshInterval you define and updates the Kubernetes Secret if the value has changed. To propagate the new value to running pods, you need either a reloader (Reloader by Stakater is common) or ESO's rolloutRestartTargets. It doesn't happen automatically without one of those two mechanisms in place.
Not sure which secrets architecture fits your team? Talk to us at Coding Protocols — we help platform teams design security architectures that are operationally sustainable, not just theoretically correct.


