Ever needed to tweak an OpenAPI spec for different environments without maintaining multiple copies?

Maybe swap out server URLs between dev, staging, and production? Or perhaps strip out internal endpoints before publishing the API docs?

OpenAPI Overlays are the answer. They let us make non-destructive modifications to specs using JSONPath expressions to target exactly what we want to change.

Think of them as surgical strikes on our API specifications.


The apply-overlay command takes an overlay document and applies it to an OpenAPI spec, giving a modified version without touching the original.

This is perfect for CI/CD pipelines where you need environment-specific variations of the same base spec.

Basic Usage

vacuum apply-overlay openapi.yaml overlay.yaml modified.yaml

This reads openapi.yaml, applies the modifications from overlay.yaml, and writes the result to modified.yaml.

What is an OpenAPI Overlay?

An OpenAPI Overlay is a separate document that describes modifications to apply to a spec. It uses JSONPath expressions to target specific parts of your API definition, then either updates or removes those parts.

Here’s a simple overlay that changes the API title and adds a production server:

overlay: 1.0.0
info:
  title: Add Production Server
  version: 1.0.0
actions:
  - target: $.info.title
    update: "My API (Production)"
  - target: $.servers
    update:
      - url: https://api.example.com/v1
        description: Production server

The target field uses JSONPath to pinpoint what you want to change, and update provides the new value. You can also use remove: true to delete parts of the spec entirely.

Remote Overlays

You don’t have to keep overlay files locally. vacuum can fetch them from URLs:

vacuum apply-overlay spec.yaml https://cdn.example.com/overlays/prod.yaml output.yaml

This is brilliant for centralized overlay management. Keep your overlays in a CDN or repository and reference them from anywhere. Perfect for teams that need to apply the same modifications across multiple services.

stdin and stdout

For CI/CD pipelines, vacuum supports reading specs from stdin and writing results to stdout.

This means we can pipe specs through the apply-overlay command without creating intermediate files:

cat openapi.yaml | vacuum apply-overlay -i overlay.yaml -o > modified.yaml

Or use it in a pipeline with other vacuum commands like bundle or any other tool:

curl https://api.example.com/openapi.json | \ vacuum apply-overlay -i prod-overlay.yaml -o | \ vacuum bundle -i - bundled.yaml

The -i flag tells vacuum to read the spec from stdin, and -o writes the result to stdout instead of a file.

Handling Warnings

When vacuum applies an overlay, it might encounter warnings.

Things like JSONPath expressions that don’t match anything or actions that can’t be applied cleanly.

By default, vacuum shows these warnings but still completes successfully.

To enable strict mode where warnings are treated as errors (useful in CI/CD to catch issues early), use the --fail-on-warnings flag:

vacuum apply-overlay spec.yaml overlay.yaml output.yaml --fail-on-warnings

With this flag, vacuum exits with code 2 if any warnings occur, making your CI pipeline fail fast.

Available Flags

Short Full Input Description
-W –fail-on-warnings bool Treat overlay warnings as errors (exit code 2)
-q –no-style bool Disable styling and color output (useful for CI/CD)
-i –stdin bool Read spec from stdin instead of a file
-o –stdout bool Write output to stdout instead of a file

Global flags like --remote, --cert-file, and --base also work with apply-overlay. Use vacuum apply-overlay --help to see all available options.

Real-World Examples

Environment-Specific Server URLs

Create different overlays for each environment:

dev-overlay.yaml:

overlay: 1.0.0
info:
  title: Development Overlay
  version: 1.0.0
actions:
  - target: $.servers
    update:
      - url: https://dev.api.example.com
        description: Development server
  - target: $.info.title
    update: "My API (Development)"

prod-overlay.yaml:

overlay: 1.0.0
info:
  title: Production Overlay
  version: 1.0.0
actions:
  - target: $.servers
    update:
      - url: https://api.example.com
        description: Production server
  - target: $.info.title
    update: "My API (Production)"

Then apply the right one for each deployment:

vacuum apply-overlay base-spec.yaml dev-overlay.yaml dev-spec.yaml vacuum apply-overlay base-spec.yaml prod-overlay.yaml prod-spec.yaml

Removing Internal Endpoints

Strip out internal-only endpoints before publishing your public API docs:

public-overlay.yaml:

overlay: 1.0.0
info:
  title: Public API Overlay
  version: 1.0.0
actions:
  - target: $.paths['/internal/*']
    remove: true
  - target: $.paths['/admin/*']
    remove: true
  - target: $.tags[?(@.name == 'internal')]
    remove: true
vacuum apply-overlay internal-spec.yaml public-overlay.yaml public-spec.yaml Now we can maintain a single source of truth for our API spec and generate environment-specific or audience-specific variations on demand. No more copy-paste madness or drift between versions.

Chaining Overlays

You can apply multiple overlays in sequence by piping them together:

vacuum apply-overlay base.yaml servers.yaml -o | \ vacuum apply-overlay -i security.yaml -o | \ vacuum apply-overlay -i metadata.yaml final.yaml

Each overlay builds on the result of the previous one, giving us composable transformations.

Pro tip: Keep overlays small and focused on specific concerns (servers, security, metadata). This makes them reusable across different specs and easier to maintain.