Environment variables and configurations in Laravel

Video thumbnail

Content Index

When we develop an application in Laravel, it is normal for certain values to change depending on the environment: database credentials, external services, debug mode, or URLs. This is where environment variables in Laravel come into play, a key piece for keeping code clean, secure, and easy to deploy.

However, although Laravel makes their use very easy, it is also common to see serious errors (especially in production) due to not fully understanding when to use env(), when to use config(), and what happens when caching the configuration. In this article, I explain all of that with practical examples and real-world usage criteria.

Environment variables are ideal for when we want to test multiple configurations in a project quickly, or when several people are developing on the same project and have different project configurations. In other words, they offer an agile and fast approach to accessing multiple configurations, but this can also bring drawbacks. Being able to change or delete environment variables by mistake from a single file can cause problems when switching from one mode to another without realizing it or deleting an environment variable required by the project; therefore, using them in production can lead to problems precisely because of this freedom.

Configuration files are excellent for holding the final production configurations of the project. Therefore, we should use environment variables in development and configurations in production. This is something the framework already tells us.

The previous article was about how to implement social authentication in Laravel.

What is an environment variable in Laravel?

An environment variable is a value external to the code that is loaded at runtime and allows for modifying the application's behavior without touching the PHP files.

In Laravel, these variables are normally defined in the .env file and are loaded thanks to the PHP Dotenv component.

Why Laravel separates configuration and code

Laravel follows a fundamental best practice of modern development:
code should not change between environments, configuration should.

Thanks to this:

  • The same code can run on local, staging, or production.
  • Credentials are not uploaded to the repository.
  • Deployments are more secure and predictable.

One of the big problems in software development occurs when we are developing an application and periodically pushing modules to production: publishing our development-only configurations along with these changes. This can be solved with the previously presented scheme simply by avoiding uploading the .env file to production and maintaining production values in the corresponding configuration files.

This does not mean that it is not recommended or professional to use environment variables in production; it should be avoided where possible, but you can use them with extreme care, keeping a minimum number of environment variables in production that may be essential to keep things as controlled as possible.

Another good use of environment variables in production is when we make major changes to the project and upload it to production, or if there is a production error that is difficult to fix through log viewing and therefore we want to test in production if everything developed works as expected. In these cases, you can uncomment the environment variables in production:

.env

APP_ENV=local APP_DEBUG=true

Test the system on the server, and when we see that everything is working as expected, comment them out again:

.env

# APP_ENV=local # APP_DEBUG=true

With this, you avoid touching the project configurations again, which are files that must be handled with extreme care.

What type of data should go in environment variables

Some clear examples:

  • Database credentials
  • API keys (Mailgun, AWS, Stripe…)
  • Cache, queue, or session drivers
  • Flags like APP_ENV or APP_DEBUG

The .env file in Laravel

What the .env file is for

The .env file is where we define the local environment variables of the project, following the format:

KEY=VALUE

Laravel automatically loads this file when the application starts.

Differences between .env and .env.example

  • .env
    • Contains real values
    • Should never be uploaded to the repository
  • .env.example
    • Is versioned
    • Serves as a template
    • Indicates which variables are necessary

Keeping an updated .env.example avoids many problems when someone new clones the project or when it is deployed in a new environment.

Why the .env file should not be uploaded to the repository

Uploading the .env implies:

  • Exposing credentials
  • Forcing development configurations onto production
  • Very serious security risks

Laravel already assumes that the .env is private, which is why it is ignored by default in .gitignore.

How Laravel works internally with environment variables

Since Laravel 5, the framework uses PHP Dotenv to load variables from the .env and expose them to PHP through $_ENV.

How and when variables are loaded

Variables are loaded:

  • When the application starts
  • Before configuration files are read

That's why you will see many lines like this in config/*.php:

'debug' => env('APP_DEBUG', false),

This is safe even with cached configuration.

Types of values supported in the .env

Laravel interprets some special values:

| Value in `.env` | Real type |
| --------------- | ------------ |
| true / false | boolean |
| null | null |
| empty | empty string |
 

You can also use quotes if there are spaces:

APP_NAME="My Application"

env() vs config(): the difference that avoids production errors

This is one of the most important parts of the article.

When to use env()

Only inside configuration files (config/*.php)

Correct example:

// config/app.php 
'env' => env('APP_ENV', 'production'),

Why you should not use env() outside of configuration files

When you run:

$ php artisan config:cache

Laravel:

  • Combines all configuration into a single file
  • Stops loading the .env

At that point, any env() used outside of config may return null.

In production, this causes bugs that are hard to trace.

More than once, I have found production bugs caused exactly by this.

How to correctly consume configuration with config()

The correct way is:

  • Read env() in config/*.php
  • Use config() in the rest of the application
  • config('app.env');

Environment variables in development and production

Recommended use in development

In development, the .env is ideal:

  • Quick changes
  • Multiple configurations
  • Total flexibility

There is no problem modifying variables frequently here.

Risks of using .env directly in production

In production, the .env:

Is easy to modify by mistake

  • Is not versioned
  • Can break the system without leaving a clear trace
  • Therefore, in my experience, the final production configuration should live in config/*.php, not depend on an editable .env.

Exceptional cases and how to handle them with care

There are specific cases (complex errors, urgent validations) where it might be useful to temporarily activate:

APP_ENV=local APP_DEBUG=true

Test, verify, and deactivate it again immediately.

It is a valid technique, but only if you know exactly what you are doing.

Configuration cache and its impact on environment variables

What php artisan config:cache actually does

  • Generates a single file with all the configuration
  • Improves performance
  • Disables loading of the .env

What happens to env() when configuration is cached

It will only work with system environment variables, not those from the .env.

That is why Laravel clearly warns:

Never use env() outside of configuration files.

Common errors when deploying to production

  • Caching configuration and then changing the .env
  • Using env() in controllers or services
  • Forgetting to clear the cache (config:clear)

Creating custom configurations in Laravel

It is possible to create custom configurations for our application, which is extremely useful for personalizing these parameters when necessary. For example, if you want to install an electronic wallet like PayPal that requires defining access keys, it is highly recommended to manage these accesses through configurations to be able to edit them more easily. They are also useful if we need to create any additional parameter for the correct operation of the application.

To do this, we must select the configuration file where we want it to be hosted. Here, it is recommended that you choose the one that most closely resembles the configuration to be created. For example, if you want to use keys to access Dropbox or Google Drive, you can choose database.php or app.php. If they are social login credentials, you can use auth.php, for example.

When it makes sense to create your own configuration

For example:

  • Keys for external services
  • Custom flags
  • Business-specific parameters

Where to locate it within the config folder

The ideal is:

  • Use an existing file if it fits (app.php, services.php)
  • Create a new one if necessary

Just like existing configurations, it is possible to use the helper function env() so that it takes the value from the .env if it exists there:

// config/custom.php return [ 'route' => env('APP_ROUTE', 'production'), ];

How to read these configurations from the application:

config('custom.route');

This approach is much safer than using env() directly.

Example

config\app.php

'app_route' => env('APP_ROUTE', "production"),

.env

APP_ROUTE=local

To access these configurations, we use the helper function config():

config('app')['env']

In which the first parameter specifies the name of the configuration file and the next parameter the key:

config('app')['env']

We could also directly reference the environment variable:

env('APP_ROUTE', "production")

Validating environment variables and avoiding silent failures

Typical problems when a variable is missing

  • Null values
  • Runtime errors
  • Hard-to-reproduce bugs

Using Env::getOrFail from Laravel 10 onwards

Laravel 10 introduces a very useful method:

use Illuminate\Support\Env; Env::getOrFail('MAILGUN_SECRET');

If the variable does not exist, it throws an exception immediately.

This allows detecting errors at startup, not when something critical has already failed.

Detecting errors as soon as possible

This approach is ideal for:

  • Production
  • External services
  • Critical configuration

Managing multiple environments in Laravel

APP_ENV and environment detection

Laravel detects the environment with APP_ENV:

App::environment('local');

.env files per environment

Laravel supports:

  • .env
  • .env.staging
  • .env.testing

This makes it easier to work with multiple environments without mixing configurations.

Creating custom files

In case it is necessary, we can create custom configuration files; we simply must create the file inside the config folder of the project, in which we must have the same structure as the current ones, for example:

config\custom.php

<?php 
  return [ 'test_config' => env('TEST_CONFIG', 'VALUE'), ];

And to access the custom file, we do it in the same way as with the current configuration files:

config('custom');

Best practices for teams and deployments

  • .env.example always updated
  • Minimum variables in production
  • Cached configuration on deploy

Final best practices for environment variables in Laravel

Quick checklist for production

  • ✅ .env out of the repository
  • ✅ env() only in config
  • ✅ config() in the rest of the code
  • ✅ config:cache in production
  • ✅ Validation of critical variables

Errors you should avoid:

  • Using env() in controllers
  • Activating APP_DEBUG in production
  • Depending on .env for critical logic

Use Settings or Environment Variables in Laravel? - Opinion

Video thumbnail

In Laravel, one of the most important topics when developing a robust application is understanding how to manage configuration and environment variables. Although both concepts seem similar, their purpose and time of use are distinct. In this article, I explain, from a practical standpoint, how they work, when it is best to use each one, and how to apply them correctly in real projects.

Why does Laravel separate configurations and environment variables?

Laravel organizes sensitive information and configurations at two levels: environment variables (.env) and configuration files (/config). This separation is not accidental but a key decision for code security and maintenance.

The purpose of the .env file

The .env file stores data that changes according to the execution environment: database, API keys, external services, or application mode (development or production). Laravel manages them through the Dotenv package, which loads the variables when the framework starts.

These variables should not be shared or versioned. They are specific to the server, so a change in production does not affect your local environment. For example:

APP_ENV=local APP_DEBUG=true PAYPAL_CLIENT_ID=xxxx

The point is that your client can inspect the application without jeopardizing its stability. That is, they shouldn't be able to "break it," create strange data, or delete the sample information. I think it's quite clear now: the demo mode allows viewing and interacting with the app, but without altering the established records.

How the configuration system in /config/*.php works

Configuration files, on the other hand, define the application's internal parameters: logging, cache, mail, queues, etc. Each file in /config contains a PHP array with values that can reference variables from the .env file.

For example, in config/app.php:

'name' => env('APP_NAME', 'MyApp'), 'debug' => env('APP_DEBUG', false),

Differences between env() and config() in Laravel

The most common confusion is when to use env() directly or when to rely on config(). Although both functions return configurable values, their scope and purpose are different.

When to use environment variables

Only use env() to initialize configurations. You should never call it directly within your application code (controllers, services, views). In those places, it is recommended to use config(), as variables can be cached and not update correctly.

When to create a custom configuration

When a value affects the business logic and not just the environment, it's appropriate to create your own configuration file. This allows you to define default values, maintain coherence, and avoid breaking the application if a variable is missing.

Practical example: demo mode controlled by environment variable

In my case, I implemented a demo mode for a sample application. I wanted users to be able to interact with the app without altering sensitive data. For that, I created a custom environment variable:

APP_DEMO=true

And in the code, I used it simply:

if (env('APP_DEMO')) { // Block certain actions }

Why not use a configuration instead of environment variables?

You're probably asking yourself: why on earth didn't I use a configuration?
On my YouTube channel, I have several videos discussing the use of environment variables and custom configurations.

Both are valid options, but in short, I almost always recommend using configurations, as working directly with environment variables can be risky.

For example, if a variable is not defined—imagine you delete the PayPal environment variable—you would break the entire application, because PayPal needs those keys no matter what.

How to create and read custom configurations in Laravel

Create a file in /config

You can create a config/demo.php file with content like:

return [ 'enabled' => env('APP_DEMO', false), ];

Access values from controllers or views

Then, you can access the value from anywhere in your application:

if (config('demo.enabled')) { // Execute demo mode }

This approach is safer, as it keeps the logic centralized and compatible with configuration caching.

Establish secure default values

Always define default values in env() calls. That way, if a variable is not present, the system will know what to do:

'paypal_client_id' => env('PAYPAL_CLIENT_ID', 'default'),

Common errors and how to avoid them

When we use the configuration scheme, the system is designed to return the environment variable's value by default if it exists.
That has the highest priority. But if it is not defined, it then takes a default value.

This is what we normally implement in 99.9% of cases.
That's why I say the ideal is to follow that structure. Everything comes this way by default: the variable is used if it's there, and if not, the base configuration is used.

Deleting or renaming a critical variable can break the application. That's why defining configurations with default values is good practice.

In short, we want to obtain a value either from the environment variable or from the configuration, but with the assurance that it exists.

If we do it correctly, we avoid errors. But if we do it incorrectly and call the variable directly, it is just as risky as having no configuration at all.

When to create a custom configuration

Every time you want to create a custom configuration—as we did in this course with the PayPal ones—the ideal is to define them correctly.

Here, for example, the production configurations should be, although I don't place them for obvious reasons (this is a sample project).
But in a real application, they must be established.

Frequently asked questions about configurations and variables in Laravel

  • What is the difference between config() and env()?
    env() reads environment variables, while config() gets values defined in the /config files.
  • Where are configurations stored in Laravel?
    In the /config folder, where each file defines a set of application parameters.
  • Is it safe to use environment variables directly?
    No. In production, they should be accessed via config(), not env() directly.
  • What happens if a variable is missing in the .env file?
    If a default value is not defined, Laravel may throw errors or behave unexpectedly.

Recommendations based on real experience

Centralizing configuration and minimizing the .env in production makes deployments more secure, predictable, and easier to maintain.

Frequently Asked Questions about environment variables in Laravel (FAQ)

  • Should I upload the .env file to the repository?
    • No. Never.
  • Can I use environment variables in production?
    • Yes, but with extreme care and only the minimum necessary.
  • What happens if I use env() with config:cache?
    • You will probably get null values.
  • Is Env::getOrFail better than env()?
    • For critical variables, yes.

Conclusion

Environment variables in Laravel are a powerful tool, but when misused, they can become a constant source of errors, especially in production.

Understanding the difference between .env, env(), and config(), along with the impact of config:cache, marks the difference between a fragile project and a professional one.

The difference between configurations and environment variables in Laravel is fundamental for developing secure, predictable, and scalable applications. Environment variables serve to define the environment and sensitive data; configurations, to establish the application's internal behavior.

In my experience, I prefer to keep things simple. If I just need to know if something is active, I use an environment variable. But if the value affects the system's logic or might be missing, I opt for a configuration with a default value. That balance between simplicity and robustness is the key to clean and stable code.

Learn now how to process heavy or high-latency tasks in the background with queues and jobs in Laravel.

We will see how to create custom variables, as well as files and recommendations when using custom configurations and environment variables.


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

I agree to receive announcements of interest about this Blog.

Andrés Cruz

ES En español