Workplace Structure

Learn how to structure your projects and configs most effectively inside a workplace.

The pattern you adopt for naming your project and configs inside Doppler has many implications when it comes to access control, secret comparison features, and more. As such, it’s important to be familiar with some of the most common and recommended ways to name and structure your projects in your Doppler workplace. Throughout this document, we’re going to use examples that use an imaginary company called Acme, Inc. that has an Acme Widgets and Acme Marketplace application.

Project Naming

The Project is the top level organizational element of your workplace. In Doppler, there are some design assumptions around what a project represents. It’s assumed that a project is a one-to-one mapping to a specific application or service that needs secrets or config variables. From an organizational standpoint, Doppler doesn’t (yet) have a way to group projects into folders, so it’s recommended that you use naming prefix and suffix conventions to group projects logically. Below are some quick best practices when naming your projects:

  • Use team name prefixes to group projects together in the project list view.
  • Use region codes as suffixes so applications and services remain grouped together.
  • Always put portions of the name you’d prefer to group by earlier in the name (e.g., <team>-<app>-<service>-<region>). This will allow you to filter for them more effectively.
  • The maximum number of Projects on any plan is 1000 (it may be possible to raise this on the Enterprise plan in some situations, but that requires review and approval by Doppler). You can see all of our platform limits here.

📘

You can keep the length of the project list in the dashboard manageable by restricting access to projects using User Groups.

Environment Naming

The Environments in your projects should typically map to deployment environments that you use for your applications and services (e.g., dev, stg, prd, qa, ci, etc.). The slug used for each of these environments is used in the API and CLI and dictates the prefix used for Branch Config names (e.g., dev_<branch-config-name>) and is referred to as the Root Config. Below are some considerations to keep in mind when naming Environments.

  • Doppler assumes Environments are all logically related to a single application or service. As such, it assumes secrets will be similar across environments and this is reflected in Doppler’s comparison features, prompts to save new secrets to other Root Configs, and some other areas as well. Notably, there are some cryptographic operations that happen that can get expensive if you have huge sets of secrets spanning large numbers of Environments — particularly if those Environments are not logically related.
  • Access control for Environments impacts access to all Branch Configs under it. So, if you give a user access to the dev Environment, they’ll have access to all Branch Configs under that Root Config (with the single exception of Personal Configs).
  • The maximum number of Environments for a project on any plan is 15. You can see all of our platform limits here.

📘

You can define the default Environments that are added to a new Project by configuring your workplace’s Default Project Environments.

Shared Projects

If you have secrets that many different projects share (e.g., DATABASE_URL, DB_USER, DB_PASSWORD, STRIPE_API_KEY, etc.), then you can take advantage of cross-project secret references to avoid duplicating these secrets and risk some getting out-of-sync. Typically, the best way to manage secrets like this is to create projects specifically for housing them (e.g., shared-db-credentials, global-credentials, etc.). You can limit access to these projects to specific admin users and references to those secrets can be added to other projects, which will then allow the users who only have access to the specific application projects to make use of them without having the ability to modify them.

  • Use a standard prefix for projects like this so they’re all grouped together (e.g., shared-, global-, etc.).
  • Take advantage of Environments to map the appropriate secrets to corresponding application Environments (e.g., shared-credentials.dev.STRIPE_API_KEY to acme-widget.dev.STRIPE_API_KEY, shared-credentials.prd.STRIPE_API_KEY to acme-widget.prd.STRIPE_API_KEY, etc.). This can be useful setting local development secrets as well (e.g., set DB_HOSTNAME in dev to 127.0.0.1).
  • Take advantage of secret visibility types to prevent users from seeing the computed value of a referenced secret by setting it to “Restricted” in the target config. Note that this will prevent the user from using the config via CLI, so you will typically not want to use “Restricted” secrets in Development environments.

📘

If you already have shared secrets set across existing projects and want to move to a shared project structure, you can use Search by Secret Value to find all the locations a secret is set to ensure they’re all using secret references.

Project Structure Examples

Below you’ll find some concrete examples showing how you can organize projects given different applications types.

Microservice

Option 1: Application + Service

This option includes the application and service name in the project names and uses branch configs purely for deployment environments like gcp or aws.

  • eng-acme-widgets-frontend
    • dev, stg, prd
      • prd_aws
      • prd_gcp
  • eng-acme-widgets-worker
    • dev, stg, prd
      • prd_aws
      • prd_gcp
  • eng-acme-marketplace-backend
    • dev, stg, prd
      • prd_aws
      • prd_gcp

Benefits

  • Better for orgs that have larger/more teams and need to separate access by

Option 2: Application

This option only includes the application name in the project name. You then create separate branch configs for each service under the main deployment environments.

  • eng-acme-widgets
    • dev, dev_frontend, dev_worker
    • prd, prd_frontend, prd_worker
  • eng-acme-marketplace
    • dev, dev_frontend, dev_worker
    • prd, prd_frontend, prd_worker

Downsides

  • You lose some access control granularity because you can only grant access at the Environment level. This means you can give a user access to the prd config, but can’t control which branch configs they have access to, so they would automatically get access to the prd_frontend and prd_worker branch configs under this layout.

Monolith App

Since the app runs as a single service/application all secrets are in a single config

  • eng-acme-widgets
    • dev, stg, prd
  • eng-acme-marketplace
    • dev, stg, prd

Region

Incorporating the region into project naming typically involves combining a previous pattern with region suffixes. Keeping the region as a suffix will ensure that the projects are sorted next to each other in the project list view.

Option 1: Application + Service + Region

This option includes the application, service and region in the project name. This results in more projects to manage, but provides the most granular access control possible.

  • eng-acme-widgets-frontend-us
    • dev, stg, prd
  • eng-acme-widgets-frontend-eu
    • dev, stg, prd
  • eng-acme-widgets-backend-us
    • dev, stg, prd

Benefits

  • You can have separate access controls for different regions.

Downsides

  • You’ll end up with more projects in your project list, which can potentially be unwieldy.
  • You don’t get to take advantage of the secret inheritance you would get from root configs if you were to create these as region branch configs instead.

Option 2: Application + Region

This option includes the application and region in the project name. You then create separate branch configs for each service under the main deployment environments.

  • eng-acme-widgets-us
    • dev, dev_frontend, dev_worker
    • prd, prd_frontend, prd_worker
  • eng-acme-widgets-eu
    • dev, dev_frontend, dev_worker
    • prd, prd_frontend, prd_worker

Benefits

  • Less project sprawl. You’ll have fewer overall projects due to not needing separate projects for each service.

Downsides

  • You lose some access control granularity because you can only grant access at the Environment level. This means you can give a user access to the prd config, but can’t control which branch configs they have access to, so they would automatically get access to the prd_frontend and prd_worker branch configs under this layout.

Option 3: Application + Service

This option includes the application and service name in the project name. You then create separate branch configs for each region under the main deployment environments.

  • eng-acme-widgets-frontend
    • dev
    • prd, prd_us, prd_eu, prd_cn
  • eng-acme-widgets-backend
    • dev
    • prd, prd_us, prd_eu, prd_cn

Benefits

  • Less project sprawl. You’ll have fewer overall projects due to not needing separate projects for each region.
  • Easy inheritance for secrets used per service – once set in the root config all regions would inherit those secrets, allowing for individual secrets to be overridden in their specific region branch config as needed.

Downsides

  • You lose some access control granularity because you can only grant access at the Environment level. This means you can give a user access to the prd config, but can’t control which branch configs they have access to, so they would automatically get access to the prd_us, prd_eu and prd_cn branch configs under this layout.

Option 4: Application

This option only includes the application name in the project name. You then create separate branch configs for each service and region under the main deployment environments.

  • eng-acme-widgets
    • dev, dev_frontend_us, dev_frontend_eu, dev_worker_us, dev_worker_eu
    • prd, prd_frontend_us, prd_frontend_eu, prd_frontend_us, prd_frontend_eu

Benefits

  • Very little project sprawl. You’ll only have one project per logical application with all your services and regions represented as branch configs.
  • Easy inheritance for broadly used secrets (i.e., secrets needed in EVERY service) by setting them in the root configs

Downsides

  • You lose access control granularity because you can only grant access at the Environment level. This means you can give a user access to the prd config, but can’t control which branch configs they have access to, so they would automatically get access to the branch configs for every service in every region for the prd environment under this layout.

Dynamic Environments

Sometimes you may need an environment that contains dynamic configs that are ephemeral, created programmatically, and subsequently deleted (e.g., configs that are associated with a pull request review app). Be sure to create a separate environment for these. Using a separate environment is ideal because you can scope an Access Token to just having write access to that environment without fear of accidentally making changes to configs in another environment.

Pull Request Review Environments

Create a separate branch config for every Pull Request using the Pull Request’s ID in the branch name. Set any shared secrets in the root config for the environment – using secret references to your dev or stg environments if needed.

  • PR Reviews / pr
    • pr_12345

Feature Branch Environments

Developers can use Personal Configs for any feature they’re working on that doesn’t require collaboration. In scenarios where multiple developers are collaborating on a new feature (or the developer is working on multiple separate features at once), they can create new branch configs under the dev environment. Naming conventions can include the developers name followed by the feature name or just the feature name.

  • dev_user_feature-name
  • dev_feature_name

Once the feature is ready for deployment, you can use the “Promote” option for new secrets added to the branch config to promote them up to the root config.

Anti-patterns

There are some ways of organizing projects that may seem like it makes sense, but can actually cause problems down the road due to how Doppler is designed to function. The below are some of the most common anti-patterns people fall into using.

Creating one project per team

Doppler currently doesn’t have a feature that allows you to group projects into logical groups or folders. This can lead you to the idea of creating a single project for each team at your company using Doppler and then create an Environment for each of your applications or services. For example, you might create a devops project and then rather than having a dev, stg, and prd config, you might have something like frontend, backend, worker and frontend_prd, frontend_stg, frontend_dev, etc.

Downsides

  • Scales poorly due to the 15 environment limit per project.
  • This incurs performance penalties the closer to 15 environments you have and the more secrets you have in your configs due to comparison operations that happen across environment on save that perform expensive cryptographic operations. This is due to the expectation that Environments map closely with deployment environments where the secrets sets are similar from one environment to the next and are all for the same logical application or service.