How to manage environment level secrets in n8n?

We have a single n8n instance for dev and prod how can we manage the secrets separately and how we can use in workflow?

Hi @mylearnings_abu

A single instance shared by dev and prod can’t really separate secrets, since there’s only one secret context in it. n8n’s intended pattern is two instances, one for dev and one for prod, with their workflows synced through Source Control.

For the secrets, the feature you want is External Secrets (Enterprise). You connect a vault like AWS Secrets Manager, Azure Key Vault or HashiCorp Vault, then point your dev instance at the dev vault and prod at the prod one. In a credential field you reference a value as $secrets.yourVaultName.secretName, so the secret never lives in the workflow itself.

If you must stay on one instance, the realistic workaround is separate dev and prod credentials, but that isn’t true isolation.

Hi @mylearnings_abu

I agree with @achamm that the “clean” way is separate dev/prod instances – that’s the only way to get real isolation for secrets and executions.

If you’re stuck with a single instance for now but you’re on a plan that supports External Secrets, there is one extra thing you can do to at least separate values logically:

  • Create two vaults in your secrets backend, e.g. dev and prod

  • Connect both in n8n under Settings → External Secrets

  • Then reference them explicitly in your credentials / expressions, e.g.:

    • {{ $secrets.dev.MY_API_KEY }} for dev

    • {{ $secrets.prod.MY_API_KEY }} for prod

That doesn’t give you hard isolation like two instances, but it does avoid having a single “mixed” credential and makes it very clear which environment a workflow is talking to.

If you share a bit more about your setup (Cloud vs self‑hosted, and which plan), people here can probably suggest a concrete pattern that fits your limits.

@mylearnings_abu hello

If you have an Enterprise cloud plan, you can connect separate vaults for each environment using the External Secrets functionality; for self-hosted you can use Credential Overwrites via environment variable or REST endpoint; but if you’re on the cloud community edition a practical solution is to Create separate credentials for dev and prod, Store the URLs/configs in a database or Google Sheets and start each workflow by fetching the correct configuration based on an environment variable ENV=dev or ENV=prod

Hi @mylearnings_abu

Running both environments on one instance is risky because a mistake in a test workflow could crash your entire system. If your business relies heavily on these automations, the safest long-term move is to set up two completely separate n8n installations—one for experimenting and one for live production.

To answer your question we are using a self hosted setup with Enterprise Plan and currently we have only one instance running

Since you’re self-hosted Enterprise but still on one instance, separate vault values help with credential hygiene, but they don’t make dev and prod truly isolated. A test workflow can still run in the same execution/runtime path as production.

The clean split is still two n8n instances sharing source-controlled workflows, each pointing at its own vault/env. If you can’t split yet, keep the short-term rule simple: prod credentials only on prod workflows, dev credentials on copied dev workflows, and no shared credential names between them. Is the blocker only credential separation, or do you also need dev runs/webhooks prevented from touching production systems?

Since you’re self-hosted Enterprise on one instance, Credential Overwrites is the cleanest pattern for this, inject secrets at the environment level via CREDENTIALS_OVERWRITE_DATA in your Docker config so they never appear in the UI or database:

environment:

  • CREDENTIALS_OVERWRITE_DATA={“ProdDB”:{“host”:“prod-db.internal”,“password”:“prod-secret”},“DevDB”:{“host”:“dev-db.internal”,“password”:“dev-secret”}}

Workflow builders create credentials named ProdDB / DevDB in the UI with the sensitive fields blank, n8n injects the real values at runtime silently.

Pair that with two vault paths in your External Secrets backend (/n8n/dev/ and /n8n/prod/), and reference them explicitly in workflows as $secrets.dev.API_KEY vs $secrets.prod.API_KEY.

The runtime isolation risk @oimrqs_ops mentioned is still real on one instance, mitigate it by keeping dev workflows disabled when not actively testing.