Skip to content
Scalpels home

Scalpels is officially launching on October 31, 2026. Special early adopter pricing is available now.

← All guides

Guide

A Comprehensive Agent's Guide to Laravel Cloud

Configure environments

· Ed Grosvenor

Laravel Cloud configures an application's connections for you. When it attaches a database, cache, bucket or managed queue, it writes the credentials and the driver selection into a separate, managed environment file. Your own environment variables sit on top of that file. Set one of the same names and you replace Cloud's value with yours.

Never set what Cloud injects

Resource Cloud sets Do not set
Database Connection details and the default connection DB_*, DB_CONNECTION, DATABASE_URL
Cache (Valkey or Redis) Connection details, CACHE_STORE, and the session driver REDIS_*, CACHE_STORE, SESSION_DRIVER
Bucket Credentials and the default disk AWS_*, FILESYSTEM_DISK
Managed queue Queue credentials and connection SQS_*, QUEUE_CONNECTION

Overriding these broke things for us twice. An agent set QUEUE_CONNECTION=sqs and production stopped processing jobs, because Cloud's managed queues use a connection named cloud. A leftover override from an earlier setup stranded about 3,900 jobs on a queue nothing was reading.

The same rule applies to documentation you write. A README or .env.example listing QUEUE_CONNECTION=redis or five DB_* variables as "required in production" teaches the next person to break their deployment. And cloud ship offers to copy your local environment file up to Cloud. Decline.

A few consequences of the separate file:

  • Interpolation does not work across it. MY_DB_HOST=${DB_HOST} cannot resolve on Cloud, because DB_HOST is not in the file being interpolated. Read the resolved connection from config() instead.
  • AWS_URL is not injected. If your code builds public object URLs from it, set it yourself or derive the URL another way.
  • A package that builds its own connection from its own variables, with a fallback such as 127.0.0.1, will never reach the database on Cloud. Have it reuse the application's resolved default connection.

Defaults that surprise

  • APP_ENV is not set. Laravel treats an unset APP_ENV as production, so every environment, staging included, runs as production. Destructive commands such as migrate:fresh refuse to run there. Set APP_ENV explicitly on non-production environments.
  • The session driver is cookie. Cloud sets SESSION_DRIVER=cookie unless a cache provides something else. Laravel's own default is database, and an app that relies on that hides the difference until it reaches Cloud. A database session driver on public pages also keeps a hibernating app's database awake. See Hibernation and idle cost.
  • Values we have read from running environments: the default database connection was pgsql, the default queue connection cloud, the default disk private (wired to the bucket), and the cache store database when no cache was attached.
  • Bucket disk configuration is replaced, not merged. Cloud's bootstrapper replaces your configured disk with a fixed set of keys. Options you added, such as stream_reads, disappear, and throw is forced to false. Large reads then buffer whole objects in memory, which matters on a 512 MB instance.

Read configuration through config()

Do not assume whether configuration is cached. Our notes disagree: one production environment reported config, events and routes as not cached, while another application behaved as if optimize had run during deploy. Check with:

cloud command:run <environment-id> --cmd='php artisan about --only=cache' --json -n --fields=exitCode,output

Then write code that works either way. Under cached configuration, env() returns null outside configuration files, and Laravel never loads the environment repository. Code that asks "was this variable explicitly set?" gets the wrong answer. Decide from config() values only, and add a test that boots the application with cached configuration, since test suites usually never do.

If you want caching, add php artisan optimize to the build command.

Changing variables

cloud environment:variables <environment-id> --action=set --key=FEATURE_FLAG --value=on --force -n
cloud environment:variables <environment-id> --action=delete --key=OLD_A,OLD_B --force -n
  • Changes apply at the next deploy. Running containers keep the old values. That also means removing a variable does not stop a running process from using it.
  • A redeploy ships whatever is on the tracked branch. Before redeploying just to pick up a variable, compare the current deployment's commit with the branch head. You may be deploying merged work nobody meant to release yet.
  • append adds without checking for duplicates. set replaces matching keys. Use set so a rerun converges.
  • Verify with a re-read, such as cloud environment:get <environment-id> --json -n --fields=name,environmentVariables, not the exit code.
  • The read shows only variables you set. Cloud's injected values never appear there. To see what the running application actually received, ask it with command:run or tinker.
  • Variable names must match ^[a-zA-Z_][a-zA-Z0-9_]*$, and one API call accepts at most 200 variables.

Prove configuration against the running app

Configuration files and environment listings describe intent. Before declaring an environment correctly configured, check from inside it:

  • the effective values, read with config('database.default'), config('queue.default') and so on;
  • a database connection, with DB::connection()->getPdo();
  • the default disk, with a put, get and delete round trip;
  • a queued job actually processed, not just dispatched.

Two configured variables are not proof that anything works. One of our applications had telemetry variables set for weeks while its credential's request count stayed at zero. Nothing had ever arrived.

Want some help?

After you buy, we will pay for an hour with one of these experts to help you get everything up and running.

  • Artisan Build

    USA

    We run Scalpels, as well as a suite of other tools for developers and development teams.

    Agency Ask for help
    Ask Artisan Build for help