DEV Community

Jeff
Jeff

Posted on Originally published at powerduck.com

Templating the servers Object with Variables for Local, Staging, and Production

Quick answer: The OpenAPI servers object supports variables that substitute parts of the base URL, so one spec can describe local, staging, and production hosts without duplicating paths. Define a variable with a default and allowed values, and clients render the template before sending requests. Use it for genuinely varying parts like host, port, or base path; do not encode secrets or per-user values in server variables.

Anatomy of a server template

Each entry in servers has a URL template that can contain placeholders in braces, plus a variables map that defines the default and optional enumeration. When a client reads the spec, it substitutes the chosen value and uses the resulting absolute URL.

With the default, the base URL renders as https://api.example.com/v1. Choosing the staging value produces a different base while every path and operation stays defined once.

Variables beyond the host

Any substring of the URL can be templated, which makes the mechanism useful for base paths, ports, or tenant segments that are part of the address. A common case is a versioned base path or a gateway prefix.

Note that ports inside a URL are part of the host string, so templating them as shown keeps the value in one place rather than scattered across operations.

Use case Appropriate Reason
Environment host selection Yes A bounded set of known deployments
API version or gateway prefix Yes Part of the address, shared by operations
Per-tenant subdomain Sometimes Only if the client selects it explicitly
Tokens or credentials No Secrets belong in auth headers, not the URL

How generated clients consume the variables

Most code generators turn the default server URL into the client's base path and expose a way to override it. Some read the enum and offer the choices, while others accept an explicit base URL parameter. The safest approach is to let the deployment inject the base URL at runtime rather than hardcoding an environment inside the spec. Server variables describe valid options; they are not a configuration store that should branch on each machine.

// Explicit base URL at runtime overrides the documented default const client = new ApiClient({ baseURL: process.env.API_BASE_URL || 'https://api.example.com/v1', });

Relative servers and local development

OpenAPI also allows a relative server URL, resolved against the location the spec is served from. This is convenient for docs hosted on the same origin as the API, but it can break code generators or tools that expect an absolute URL and do not know the document's base. Prefer an absolute template with a localhost variable for local development, and reserve relative URLs for documentation that is always served from a known origin.

Common mistakes and how they surface

A missing default makes the template ambiguous, and clients that cannot prompt for a value will fail or guess. An enum that does not include a value the deployment actually uses creates a spec that cannot describe a real environment. Trailing slashes are another frequent source of trouble: if the server URL ends with a slash and an operation path also begins with one, some clients produce a double slash that the server treats as a different route. Keep the server URL without a trailing slash and start every operation path with one. When an AI agent edits the servers block, ask it to render each template to a concrete URL and confirm the enum and default agree, rather than assuming the placeholders resolve.

Keeping the server list honest

List only environments that actually exist and are reachable. A long server list full of decommissioned hosts misleads consumers and bloats generated configuration. Treat the servers block as part of the contract, review it when infrastructure changes, and use linting to enforce that every variable has a default and that enum values are strings. This keeps the spec a reliable source for both documentation and generated clients.

Server variables and the OpenAPI document itself

Remember that the servers block can be declared at different levels: globally at the document root, or overridden on individual operations when a path is served from a different host. A path-level server replaces rather than merges the global entry, so a reader that only looks at the top-level list can miss a special case. When you audit a spec, resolve the effective server for each operation rather than assuming the global default applies everywhere, and document why an operation overrides it so the exception is intentional rather than accidental.

Frequently asked questions

Can I put an API key in a server variable?

No. Credentials must never appear in the URL, which is logged and cached. Use a security scheme and send the key in a header or other supported location.

What happens if a client does not choose a variable value?

It uses the declared default. If no default exists, behavior is undefined and many clients will error. Always provide a default for every variable.

Should I list every local developer port in the enum?

No. The enum should contain meaningful, shared options. For arbitrary local ports, expose a configurable base URL in the client rather than trying to enumerate every developer machine.

Are server variables the same as path parameters?

No. Path parameters vary per operation call and are defined on the operation, while server variables choose the base address and apply to every operation. Keep resource identifiers in path parameters and environment choices in server variables.

This is part of the The OpenAPI Guide — start there for the structural decisions that keep a spec usable across tools and environments.

Top comments (0)