---
title: What every dev should know about using Environment Variables
authors: Kadi Kraman
published: May 23, 2025
categories: Development
tags: environment variables
---

_Note: This post was originally published in 2024 and has been updated to reflect the current version of Expo.  _ 

## What are environment variables and how to configure them

An environment variable is a value that is set from outside the program. The purpose of environment variables is to be able to change your program functionality without having to rebuild and/or redeploy the program.

We will look at how environment variables work, their main usages, common pitfalls, and the best approaches for using environment variables in Expo React Native apps.

## How do environment variables work?

Using Node.js as an example, you could set an environment variable inline before executing your program:

```bash
API_URL=https://api.app.com node code.js
```

Here, we’re setting `API_URL` to `https://api.app.com` and then executing the code in **code.js** with `node`. During application initialization, the `API_URL` variable is loaded into `process.env`, so that anywhere within **code.js**, you can access it via `process.env.API_URL` and it will evaluate to `https://api.app.com`.

Now say that you had two API environments: development and production. The code in **code.js** needs to be the same for both, the only difference is that the development version should send requests to `http://localhost:3000` while the production version should use `https://api.app.com`.

Without environment variables, you’d need to hardcode the api url in your codebase and have two separate versions of the file for development and production.

With environment variables however, you can use the exact same **code.js** file to support both environments by setting the `API_URL` environment variable to the correct value before executing the program, using

```bash
API_URL=http://localhost:3000 node code.js
```

for development and

```bash
API_URL=https://api.app.com node code.js
```

for production.

## Environment variables and security

_Is it safe to add secrets to environment variables?_ Let us first establish what a “secret” is: a secret, in this context, is anything that you wouldn’t be comfortable with anyone else having access to.

For example, your OpenAI `apiKey` would be a secret, because it is a service where you had to create an account and you pay per request. So any malicious actors using your `apiKey` would use up your usage limits. Any credentials, private keys or passwords such as ‘database connection strings’ are also secrets.

### So is it safe to add secrets to environment variables?

It’s only safe when it is not possible for the user to access the source code where the environment variable is used.

- websites: **not safe**, because you can inspect the page source in the browser
- mobile and desktop apps: **not safe**, because you can inspect the app source
- web APIs: **safe** because the program is run on a server and the source code is hidden

In summary: **never store secrets in environment variables that are used in client side code** because any code you add to a website or a mobile app (even if it’s added using an environment variable) can be accessed in plain text.

## Common uses of environment variables

Environment variables can be used for many scenarios when there is a need for changing specific application runtime behavior. Here are the three most common use cases you’re likely to run into:

1. **Feature toggles: **For example, if you’re building an Expo app, and you add `EXPO_DEBUG=true` in front of any Expo command such as `EXPO_DEBUG=true npx expo start`, you’ll see additional logging from the process.
2. **Setting environment-specific values:** It is common for modern software projects to have at least a `development` and a `production` environment, which should connect to the `development` vs `production` APIs, payment providers and services respectively. Using environments variables will allow developers to use the same app or website code with only the relevant values replaced.
3. **Storing secrets:** As said above - **never store secrets in client side code** - but for server side code, using environment variables for secrets is paramount. It will allow developers to securely store their code in source control and store the secrets (such as database connection strings, API keys) separately in environment variables that are only pulled out when the server side code is being deployed.

### .env files

Storing environment variables in **.env** files is a widely adopted, though not a standardised approach. With this approach, you will create a file called **.env** at the root directory of your project and enter all your environment variables as key value pairs:

```bash
API_URL=https://api.app.com
ANALYTICS_KEY=key
STAGE=production
LANGUAGE=en
```

The way you then load and access these variables can vary hugely based on the language and library you use.

### Environment variables with Expo

In your Expo apps and Websites, all environment variables that are used in code will have to be prefixed with `EXPO_PUBLIC_`, so e.g. your `API_URL` would become `EXPO_PUBLIC_API_URL`. We designed it this way to make it absolutely clear that anything stored in these environment variables should not be a secret, as it will be used in the frontend code.

These environment variables are <u>inlined</u> during build time. This means that when the JavaScript bundle is being generated, the bundler replaces all instances of `EXPO_PUBLIC_API_URL` with the actual value in the resulting bundle which is then converted to Hermes bytecode.

There are three ways to set environment variables in Expo projects:

1. [EAS Environment Variables](https://expo.dev/blog/environment-variables)
2. **.env** files
3. **eas.json**

If you use EAS, you’ll usually end up with a combination of the three to ensure your environment variables are set in all cases.

### Using EAS environment variables

[EAS (Expo Application Services)](https://docs.expo.dev/eas/) is the popular set of integrated cloud services for Expo and React Native apps. Developers use EAS to build, update, and submit their applications.

EAS has first class support for environment variables which you can manage via the Expo website or the CLI. Each project has three environments that mirror the three main build profiles:

- **development**: for development client build
- **preview**: for other configurations
- **production**: for app store build

and are three levels of visibility:

- **plain text**: visible on the website, in EAS CLI, and in logs.
- **sensitive**: obfuscated in build and workflow jobs logs. You can use a toggle to make them visible on the website. They're also readable in EAS CLI.
- **secret**: not readable outside of the EAS servers, including on the website and in EAS CLI. They are obfuscated in build and workflow jobs logs.

![Environment variables](https://cdn.sanity.io/images/9r24npb8/production/bb58c047602bf4aa1a0aae1d974d3733bc3f2295-2042x1182.png)

Each build profile may be assigned an environment in **eas.json**:

<!-- eas.json -->
```json
{
  "build": {
    "production": {
      "environment": "production"
      ... 
    },
    "preview": {
      "environment": "preview"
      ... 
    },
    "development": {
      "environment": "development"
      ... 
    },
    "my-profile": {
      "environment": "production"
      ... 
    }
  }
}
```

Now whenever you `eas build` on EAS servers, the environment variables for the configured environment will be used.

### Using EAS environment variables for local development

For local development, the EAS environment variables can be pulled down into a local `env.local` via the EAS CLI:

```console
$ eas env:pull --environment development
```

Only plain text and sensitive environment variables may be pulled down like this, as secrets can never leave the EAS servers.

### Using EAS environment variables for EAS Update

The `eas update` command supports the `--environment` flag. For example the following command will create an update using the production environment variables:

```console
$ eas update --environment production
```

If an `--environment` flag is not provided, environment variables from any local `env` files will be used. Note also that the only plain text and sensitive environment variables can be embedded in the update.

### Setting environment variables in eas.json

For build profile-specific environment variables, it is also possible to define them in **eas.json** directly:

```json
{
  "build": {
    "development": {
      "env": {
        "APP_VARIANT": "development"
      },
      ... 
    },
    "preview": {
      "env": {
        "APP_VARIANT": "preview"
      },
      ... 
    },
    "production": {
      "env": {
        "APP_VARIANT": "production"
      },
      ... 
    },
    "my-profile": {
      "env": {
        "APP_VARIANT": "development"
      },
      ... 
    }
  },
}
```

This may be handy for environment variables used in `app.config.js`, for example your app variant.

Variables set in the `eas.json` can not be used in `eas update` or `eas deploy`.

### Environment variables in EAS Hosting

[EAS Hosting](https://docs.expo.dev/eas/hosting/introduction/) is a service for deploying your Expo Router web project and API routes. With the ability to deploy API routes - which are fully server side - we are now able to include sensitive environment variables in the server side code.

For deploying a web project with environment variables, note that the environment variables for the client- and server-side code are included at different steps:

- Running `npx expo export --platform web` will inline the `EXPO_PUBLIC_` variables in the frontend code. The `--environment` flag is not supported in the export command, so you'll need to pull down the variables you need before building with `eas env:pull`
- `eas deploy --environment production` will include all plain text and sensitive variables for the given environment (in this case, `production`) in the API routes. If there are any local **env** files, EAS environment variables loaded with the `--environment` flag will take precedence over ones defined in **.env** and **.env.local** files.

Since secret environment variables are designed to never leave the EAS servers, they cannot be used via the `--environment` flag which is why it is not currently possible to add secrets to API routes even though it would be safe to do so. Set any values used in API routes as **Sensitive**.

### Environment variables resolution order

When environment variables are set in multiple places, they are resolved in the following order:

**eas.json** -> **.env **files -> EAS environment variables

So if the same value was defined in all three, the EAS environment variables one would get applied.

The following caveats exist:

- `eas build` will ignore any **.env **files that are in **.gitignore**
- Environment variables that are set in **eas.json** cannot be used by `eas update`
- "Secret" visibility EAS environment variables can only be used during `eas build` on the EAS servers. They cannot be pulled down locally or included in commands via the `--environment` flag

### Summary

- Environment variables can be used to change your program functionality - change the API endpoint, enable additional logging, reveal hidden features - from outside the program.
- Any environment variables in frontend code - websites, mobile apps - are available in plain text so you should never store anything secret in them (such as API keys).
- [EAS environment variables](https://expo.dev/blog/environment-variables) provide a comprehensive environment management solution for Expo React Native projects
- Environment variables may also be set in **.env** files and in **eas.json**
- With [EAS Hosting](https://docs.expo.dev/eas/hosting/environment-variables/), client and server side environment variables are embedded at different steps and server side code may include sensitive values like API keys and DB connection strings