— Developer Tools

Free .env File Diff

Paste two .env files to see which variables are missing on either side, which values changed, and which keys are defined twice.

— Samples
Keys listed 2Duplicates 0Valid
Live

What is a .env File Diff?

A .env file holds an app’s configuration as KEY=value lines, and every environment, from a laptop to production, has its own copy. This tool compares two .env files and lists the variables that are missing, the values that differ, and the keys defined twice.

Values are read the way the dotenv package reads them: an optional export prefix, single-quoted values kept literally, double-quoted values that expand \n and may span lines, and unquoted values that end at a space followed by #. Keys are compared after that parsing, so formatting differences alone never show as changes.

Key Features

Missing Variables Found Fast

The Missing view lists keys that exist in only one file, which is how a deploy fails for want of a new setting.

Real Value Changes Only

Quoting, spacing and comments are normalized before comparing, so PORT=3000 and PORT = "3000" count as the same value.

Duplicates Called Out

A key defined twice in one file is reported with its line, since only the later value is used and the earlier one silently stops mattering.

Multi-Line Secrets Handled

Private keys and certificates written across several lines in double quotes are read as one value and compared correctly.

Secrets Never Leave the Page

Both files are parsed in your browser and nothing is uploaded, which matters when the values are passwords and API keys.

Perfect for everyone

  • Developers syncing .env.example with real environments
  • DevOps engineers preparing deploys
  • Teams auditing configuration drift between staging and production

How to Use the .env File Diff

Paste two env files, choose what to show, and fix the gaps.

1

Paste the First File

Usually the reference: .env.example from the repository, or the environment that works.

2

Paste the Second File

The file to check, such as .env.production or a teammate’s local file. Redact secret values first if you’re sharing your screen.

3

Choose Missing, Changed or All Keys

Missing lists keys in only one file, Changed lists keys with different values, and All keys lists everything with its status.

4

Fix the Gaps

Add missing keys to the file that needs them, and check that changed values are intentional, such as a production database URL.

Worked Examples

Env Files Compared

Each example is the first file, three dashes, then the second file. The answer is this tool’s report in the mode on the chip, so decide which keys stand out before revealing it.

REF_001Missing keys

“PORT=3000 DATABASE_URL=postgres://localhost/app REDIS_URL=redis://localhost --- PORT=8080 DATABASE_URL=postgres://db.internal/app”

REF_002Changed values

“PORT=3000 DATABASE_URL=postgres://localhost/app REDIS_URL=redis://localhost --- PORT=8080 DATABASE_URL=postgres://db.internal/app”

REF_003Formatting isn’t a change

“export NODE_ENV=production PORT = 3000 # local port --- NODE_ENV="production" PORT=3000”

REF_004Hash signs

“COLOR=#ff0000 HASH=abc#def --- COLOR="#ff0000" HASH=abc”

REF_005Escaped vs real line break

“KEY="line1\nline2" --- KEY="line1 line2"”

REF_006Single vs double quotes

“GREETING='hello\nworld' --- GREETING="hello\nworld"”

REF_007Duplicate key

“PORT=3000 DEBUG=true PORT=4000 --- PORT=4000”

REF_008Identical files

“A=1 B=2 --- A=1 B=2”

REF_009Missing equals sign

“DATABASE_URL postgres://localhost/app --- DATABASE_URL=postgres://localhost/app”

REF_010Invalid key name

“API_KEY=abc --- 2FA_SECRET=xyz”

Parsing Rules

How .env Values Are Read

There’s no formal .env standard, but most loaders copy the dotenv package. These are the rules this comparison applies before deciding two values differ.

01 / KEYVALUE

KEY=value Per Line

Each line sets one variable, with the name before the first equals sign. Spaces around the equals sign are ignored.

“What does PORT = 3000 set PORT to?”

02 / LINES

Lines Starting With # Are Comments

A line whose first non-space character is # is skipped, which is how .env.example files document each setting.

“Is # PORT=3000 a variable?”

03 / INLINE

Inline Comments Need a Space

In an unquoted value, a # preceded by whitespace starts a comment. abc#def keeps the # because nothing separates it.

“What is the value of HASH=abc#def?”

04 / QUOTE

Quote Values Containing #

Colours and passwords often contain #. Wrapping the value in quotes keeps everything inside as data.

“How do you set COLOR to #ff0000 safely?”

05 / SINGLE

Single Quotes Are Literal

Inside single quotes nothing is expanded, so a backslash and n stay as two characters.

“Does '\n' in single quotes become a line break?”

06 / DOUBLE

Double Quotes Expand \n

Inside double quotes, \n becomes a real line break. That’s how a private key fits on one line.

“Does "a\nb" contain a line break?”

07 / QUOTED

Quoted Values Can Span Lines

A double-quoted value can continue over several lines until the closing quote, which suits PEM certificates.

“Can a value cover several lines?”

08 / EXPORT

export Is Optional

A leading export lets the same file be sourced by a shell. dotenv ignores the word and reads the variable normally.

“Is export PORT=3000 the same as PORT=3000?”

09 / THE

The Last Definition Wins

If a key appears twice, the later line overrides the earlier one. The comparison uses that later value and lists the duplicate.

“PORT=1 then PORT=2. What is PORT?”

10 / EMPTY

Empty Is Not Missing

KEY= sets the variable to an empty string, while leaving the line out doesn’t set it at all. Apps often treat the two differently.

“Is KEY= the same as no KEY line?”

How Different Tools Read .env Files

The common rules hold almost everywhere, but a few loaders differ in ways that matter.

dotenv for Node.js

The reference behaviour used here. It never overrides variables already set in the environment unless told to.

Node.js --env-file

Node 20.6 and later load a .env file natively with --env-file, following dotenv’s rules closely, without the package.

Docker Compose

env_file and the project .env file accept KEY=value lines, and recent versions handle quotes and interpolation like dotenv. Older versions kept quotes as part of the value.

python-dotenv

Follows the same quoting and comment rules and also supports variable expansion such as $HOME and braced forms in values.

Next.js and Vite

Both load .env, .env.local and mode-specific files in a set order, and expose only variables with a public prefix, NEXT_PUBLIC_ or VITE_, to the browser.

Shell source

Sourcing a .env with a shell runs it as a script, so spaces around the equals sign break it and $ expands. Files meant for both should avoid those.

.env Mistakes Worth Catching

Most configuration bugs between environments come from one of these.

Tip 01

Forgetting to Update .env.example

A new variable added locally but not to .env.example breaks the next person’s setup. Compare the two before every merge.

Tip 02

Committing Real Secrets

A .env with production values belongs in a secret manager, not in git. Keep only placeholders in committed files.

Tip 03

Unquoted Hash Signs

A password like pa ss#word is cut at the # because a space comes before it. Quote values that contain # or spaces.

Tip 04

Duplicate Keys

Two definitions of the same key mean the earlier one is ignored, often a leftover from copying blocks between files.

Tip 05

Trailing Spaces in Values

Unquoted values are trimmed by dotenv but not by every loader. Quote values where a trailing space would matter.

Tip 06

Escaped Versus Real Line Breaks

A private key stored with \n in one environment and real line breaks in another is the same value, which this comparison recognises.

Tip 07

Assuming the File Wins

dotenv doesn’t overwrite variables already set by the host or CI. A value in the .env file can be silently ignored in production.

Tip 08

Public Prefixes Exposing Secrets

In Next.js and Vite, a NEXT_PUBLIC_ or VITE_ prefix sends the value to every browser. Keep secrets without those prefixes.

Keeping Environments in Sync

A diff finds drift once. These habits keep it from coming back.

Tip 01

Treat .env.example as the Contract

List every variable the app reads in .env.example, with a placeholder and a comment. Then any environment can be checked against it.

Tip 02

Validate at Startup

Have the app check required variables when it boots, with a schema library such as zod or envalid. A missing key then fails loudly instead of later.

Tip 03

Keep Secrets in a Manager

Store production values in a secret manager or the platform’s settings, and generate the .env only where it’s needed.

Tip 04

Check in CI

A small CI step can compare .env.example with the variables your code references, and fail when a new one is undocumented.

Tip 05

Name Variables Consistently

Upper-case names with underscores and a shared prefix per service, such as PAYMENTS_, make missing and duplicate keys easier to spot.

Tip 06

Comment Why a Value Differs

When staging and production intentionally differ, say so in a comment. The next comparison then explains itself.

When to Compare .env Files

Before deploys, after merges, and whenever an app works in one place but not another.

Before a Production Deploy

Compare .env.example with the production settings to catch a new variable nobody added to the server.

Onboarding a Developer

Check a new teammate’s local .env against the example file to find the setting their app is missing.

Debugging Works on My Machine

Compare a working and a broken environment to find the value that differs, such as a feature flag or a URL.

Reviewing a Pull Request

When a change adds variables, confirm the example file and the deployment config both gained them.

Migrating Hosting Providers

Export variables from the old platform and the new one as .env text, then confirm nothing was lost in the move.

Auditing Staging Against Production

List every key whose value differs, so intentional differences are documented and accidental ones are fixed.

Cleaning Up Old Variables

Keys present only in an old environment are often unused. Confirm in code, then remove them.

Frequently Asked Questions