Skip to content


Vapor's Environment API helps you configure your app dynamically. By default, your app will use the development environment. You can define other useful environments like production or staging and change how your app is configured in each case. You can also load in variables from the process's environment or .env (dotenv) files depending on your needs.

To access the current environment, use app.environment. You can switch on this property in configure(_:) to execute different configuration logic.

switch app.environment {
case .production:

Changing Environment

By default, your app will run in the development environment. You can change this by passing the --env (-e) flag during app boot.

swift run App serve --env production

Vapor includes the following environments:

name short description
production prod Deployed to your users.
development dev Local development.
testing test For unit testing.


The production environment will default to notice level logging unless otherwise specified. All other environments default to info.

You can pass either the full or short name to the --env (-e) flag.

swift run App serve -e prod

Process Variables

Environment offers a simple, string-based API for accessing the process's environment variables.

let foo = Environment.get("FOO")
print(foo) // String?

In addition to get, Environment offers a dynamic member lookup API via process.

let foo = Environment.process.FOO
print(foo) // String?

When running your app in the terminal, you can set environment variables using export.

export FOO=BAR
swift run App serve

When running your app in Xcode, you can set environment variables by editing the App scheme.

.env (dotenv)

Dotenv files contain a list of key-value pairs to be automatically loaded into the environment. These files make it easy to configure environment variables without needing to set them manually.

Vapor will look for dotenv files in the current working directory. If you're using Xcode, make sure to set the working directory by editing the App scheme.

Assume the following .env file placed in your projects root folder:


When your application boots, you will be able to access the contents of this file like other process environment variables.

let foo = Environment.get("FOO")
print(foo) // String?


Variables specified in .env files will not overwrite variables that already exist in the process environment.

Alongside .env, Vapor will also attempt to load a dotenv file for the current environment. For example, when in the development environment, Vapor will load .env.development. Any values in the specific environment file will take precedence over the general .env file.

A typical pattern is for projects to include a .env file as a template with default values. Specific environment files are ignored with the following pattern in .gitignore:


When the project is cloned to a new computer, the template .env file can be copied and have the correct values inserted.

cp .env .env.development
vim .env.development


Dotenv files with sensitive information such as passwords should not be committed to version control.

If you're having difficulty getting dotenv files to load, try enabling debug logging with --log debug for more information.

Custom Environments

To define a custom environment name, extend Environment.

extension Environment {
    static var staging: Environment {
        .custom(name: "staging")

The application's environment is usually set in entrypoint.swift using Environment.detect().

enum Entrypoint {
    static func main() async throws {
        var env = try Environment.detect()
        try LoggingSystem.bootstrap(from: &env)

        let app = Application(env)
        defer { app.shutdown() }

        try await configure(app)
        try await app.runFromAsyncMainEntrypoint()

The detect method uses the process's command line arguments and parses the --env flag automatically. You can override this behavior by initializing a custom Environment struct.

let env = Environment(name: "testing", arguments: ["vapor"])

The arguments array must contain at least one argument which represents the executable name. Further arguments can be supplied to simulate passing arguments via the command line. This is especially useful for testing.