hashicorp/vault
Background
This page collects design context that doesn't belong on a single subsystem page: why Vault makes the choices it does, what's deliberately not implemented, and the OSS-vs-Enterprise split that confuses every new contributor at least once.
Why a single binary
Vault could have been split into a daemon and a separate plugin host. Instead it's one binary that exec's plugins on demand. Reasons:
- Operators want to install one thing, not five.
- The OSS distribution is small and self-contained.
- Built-in plugins ship in-process for performance; only operator-registered plugins fork.
Why HCL for config
hashicorp/hcl is shared across the HashiCorp tool suite (Terraform, Consul, Nomad, Boundary, Waypoint). Using HCL means Vault config is familiar to anyone running other HashiCorp tools and benefits from upstream improvements. The parser supports both HCL and JSON syntax, so machine-generated configs can use JSON.
Why integrated Raft is the default storage
Before integrated Raft (1.4, 2019), HA required Consul or etcd. Operators consistently complained about the operational surface area. Embedding Raft turned Vault into its own consensus cluster with no external dependency, which:
- Reduced the operational footprint to one binary.
- Let operators audit storage and consensus together.
- Enabled snapshot-based DR within a single cluster.
External storage backends are still supported because deployments using Consul or postgres have valid reasons.
Why backends speak through logical.Backend
Backend code is the largest contribution surface in Vault — every cloud provider, database, and identity system gets one. Forcing them through a single logical.Backend interface means:
- The same router, ACL, audit, lease, and replication logic applies everywhere.
- Plugins can be in-process or out-of-process without code changes (
sdk/plugin/is just a gRPC adapter for the same interface). - The framework backend (
sdk/framework/) provides a high-level builder that handles paths, fields, OpenAPI, and existence checks.
Why so many _ce.go and _oss.go files
Vault Enterprise is built from the OSS source tree plus a closed-source overlay. The OSS tree carries one-line stub functions wherever Enterprise needs to plug in different behavior. The naming convention:
_ce.go— Community Edition stub. Enterprise replaces with a real implementation._oss.go— older convention, same idea.entExtend...,entAdd...— symbols that the Enterprise overlay implements.
If you're touching one of these files, the rule of thumb is: don't change the function signature. Enterprise depends on the signature being stable. Add new fields or arguments by introducing new functions or extending in a way that's backwards-compatible.
Why the activity log is one giant file
vault/activity_log.go (117k bytes) absorbed a lot of features over the years: client counting, billing rollups, replication-aware aggregation, retention. Splitting it has been discussed but is hard because the bitmap state machine is tightly coupled. New contributors should not feel obligated to refactor it.
The Enterprise-only feature list
What the OSS tree references but does not implement:
| Feature | Where the seam is |
|---|---|
| Performance & DR replication | vault/replication/, dozens of _oss.go stubs |
| Sentinel policy programs | vault/policy_store.go (storage), engine is closed-source |
| Control groups (multi-party authz) | Policy hooks in vault/policy.go |
| Step-up MFA on individual paths | vault/login_mfa_ce.go |
| HSM / PKCS#11 seal types | vault/seal/ plugin point |
| FIPS 140-2 builds | Build tag and crypto provider swap |
| Full nested namespaces | vault/namespaces.go plus identity store namespace handling |
| KMIP server | Not present in OSS |
| Transform secret engine | Not present in OSS |
| Key Management secrets engine | Not present in OSS |
If you contribute to OSS, you'll see references and stubs for these. Don't try to remove them.
Why everything routes through Core.HandleRequest
Centralizing the per-request pipeline means every cross-cutting concern — token check, ACL, audit, lease, quota, identity, replication forwarding — happens in one place. Every backend gets these for free. The cost is that vault/request_handling.go (3,140 lines) is dense; the upside is no backend can accidentally bypass authentication.
Why the public API never broke /v1/
/v1/ was decided in 2015. Breaking it would require rewriting every Vault user's integration code. Changes happen via:
- Additive endpoints (new paths under existing mounts).
- Deprecation cycles (warn for a few minor versions, then remove or alias).
- Feature flags surfaced via
sys/internal/ui/feature-flags.
This trades elegance for stability — and it's the right call for a security-critical service.
Why versioned plugin protocol
Plugins from before v5 used a non-multiplexed gRPC protocol; the v5 protocol added multiplexing so one process can serve many roles (essential for the unified database/ mount). The OSS tree carries both plugin.go and plugin_v5.go so old plugins still work.
Migration context worth knowing
- GitHub plugins moved out of the repo (~2018): every
vault-plugin-*repo is its own module now. - HCL v1 → v2 (~2018): config parsing was rewritten without changing the user-facing grammar.
- Database plugin protocol v5 (~2022): unified all SQL backends behind one interface.
- OIDC provider (~2022–2023): Vault became an OIDC issuer, not just a consumer.
- IBM acquisition (Apr 2025): copyright headers updated; no source-license change.
- Vault 2.0 (Apr 2026): the
release/2.0.xbranch became the new active major;1.21.xis the previous LTS.
Pitfalls
- Don't import
vault/...from outside this repo. It's not supported. Useapi/orsdk/. - Don't add direct file I/O to backends. Use the
logical.Storageview they're handed. - Don't bypass the audit broker.
Core.HandleRequestdoes this for you; don't shortcut. - Don't assume a single namespace. Always read namespace context from
context.Context. - Don't delete
_ce.go/_oss.gostubs. They look empty, they're not.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.