---
title: Organizing feature flags using environments and projects
toc_max_heading_level: 2
---

As your use of Unleash grows from a handful of developers to hundreds or even thousands, you need to ensure you can maintain control, security, and velocity across your organization.

This guide helps you design a structure around Unleash that is scalable and secure. By following these recommendations, you can establish a robust feature management system that supports diverse teams, complex release lifecycles, and enterprise-grade security requirements.

We'll cover how to:
- [Maximize the capabilities of projects and environments](#projects-and-environments-overview) and the [unified flag model](#the-unified-flag-model).
- [Structure your Unleash setup to mirror your organization](#design-your-project-setup) and [release pipeline](#design-your-environments).
- [Design a project architecture that balances open collaboration](#design-for-collaboration-and-visibility) with granular access control.
- [Secure your setup](#secure-your-setup) with environment-specific permissions, SSO, and API tokens.
- [Manage flag configurations consistently](#manage-flag-configurations-across-projects-and-environments) using segments, release templates, and dependencies.
- [Establish best practices](#best-practices-for-long-term-maintenance) for scaling in the long run.

## Projects and environments overview
**Projects** and **environments** are the two main ways to organize your feature flags in Unleash.

Think of them this way:

- **Projects organize *who***. They group related flags to align with your organizational structure—such as teams, applications, or business units—and are the primary tool for managing access control.

- **Environments organize *where***. They represent the stages in your deployment pipeline—like development, testing, and production—and control what a flag does in each of those stages.

![The password tab has a toggle that you can turn off.](/img/projects-environments.png)

A single [feature flag](/reference/feature-toggles) is defined once within a [project](/reference/projects), but its configuration (its on/off state and activation strategies) can be different in each [environment](/reference/environments). This separation allows you to manage a feature's entire lifecycle safely and efficiently.

## The unified flag model

A core architectural principle in Unleash is the **unified flag model**.

This means a feature flag is a single, logical entity that exists across all your project's environments. The flag's name, description, and other core metadata are defined once. What changes from one environment to the next is its configuration—the activation strategies, rollout percentages, and variants.

This contrasts with approaches in other feature flag providers where you might create entirely separate flag objects for each environment (for example, `new-checkout-dev`, `new-checkout-prod`). That method can lead to configuration drift and makes it difficult to trace a single feature's journey.

The unified flag model in Unleash offers several key advantages:
- **Holistic view and traceability**: You get a complete, unified view of a feature's journey. At a glance, you can see that the `new-checkout-flow` flag is enabled for your internal QA team in the test environment, rolled out to 10% of users in pre-production, and currently disabled in production. This eliminates the need to track separate flag instances across different systems, reducing mental overhead and making audits simpler.
- **Simplified rollout workflow**: Promoting a feature from one stage to the next doesn't involve creating a new flag. Instead, you simply update the configuration of the existing flag in the next environment. This workflow is more intuitive, less error-prone, and aligns with the natural progression of a feature through the development lifecycle.
- **A single source of truth**: Because the flag's essential metadata is defined once, you maintain a consistent source of truth. The purpose of `checkout.new-payment-gateway.web` is the same everywhere, preventing the configuration drift and confusion that can arise when managing separate flag definitions per environment.

## Design your environments

Every project in Unleash contains a set of environments. You should create a set that mirrors your development and release pipeline.

When you configure an environment in Unleash, you define two properties:
- **Name**: A custom, human-readable name of your choice. This should match the environment in your workflow, such as `dev`, `qa`, or `live`.
- **Type**: One of four predefined options: `development`, `test`, `pre-production`, or `production`. This environment type is important for [flag lifecycle](/reference/feature-toggles#feature-flag-lifecycle), helping you improve your workflows and flag cleanup.

| Release phase/name | Purpose                                                | Environment name | Environment type   |
|--------------------|--------------------------------------------------------|-----------------|--------------------|
| Development        | Local developer machines or shared development servers | `development`   | `development`      |
| Testing            | For automated tests and manual QA                      | `testing`       | `test`             |
| Staging            | Production-like environment for final validation       | `staging`       | `pre-production`   |
| Production         | Live environment serving end-users                     | `production`    | `production`       |

The power of environments is that a single feature flag exists once within a project, but its state and configuration can be different in each environment.

For example, the flag `new-dashboard` can be:
- **On** in the `development` environment for all developers.
- **On** in the `testing` environment, but only for users in the "QA" segment.
- **Off** by default in `production`, but enabled for a small percentage of users for a gradual rollout.

This separation is critical for safety. It allows developers to work freely in development without impacting production, lets QA teams create specific testing scenarios, and gives product teams fine-grained control over the production rollout.

## Design your project setup

Every feature flag in Unleash must belong to a project. A new Unleash instance includes a default project, but creating custom projects is essential for scaling effectively.

Projects help you:
- **Establish clear ownership and context**: By grouping flags into logical containers like `payments-team`, `mobile-app`, or `q3-initiatives`, you immediately provide context and identify responsibility.
- **Understand technical debt at a glance**: Each project has its own [dashboard](/reference/technical-debt#project-status) that gives you an instant view of its health, including metrics, recent activity within the project, and information on project-specific resources.
- **Define specific settings**: You can configure settings at the project level, such as a default activation strategy or requiring [approvals for changes](/reference/change-requests) in production environments.
- **Manage collaboration and visibility**: Projects can be set to [open, protected, or private](/reference/project-collaboration-mode), defining who can access the project or submit change requests.

![Project status dashboard](/img/project-health.png)

## Choose a project structure

Choosing how to structure your projects is a critical architectural decision. The right model depends on your team structure, software architecture, and governance requirements.
The goal is to organize your flags in a way that matches how your teams actually work. Avoid putting all flags into one large project, as it quickly becomes difficult to manage permissions and overwhelms users with irrelevant information.

Here are some common and effective strategies for structuring your projects:

**By team or squad**

If your organization is composed of autonomous, cross-functional teams that own features end-to-end, grouping flags by team is an excellent model.
- **Project name**: `payments-squad`, `mobile-core-team`, `growth-hacking`.
- **Pros**: Clearly maps ownership, simplifies access control, and reduces cognitive load for team members.
- **Cons**: May be less intuitive if features often span multiple teams.

**By application or service**

If your teams are structured around specific microservices or applications, organizing projects by that boundary is a natural fit.

- **Project name**: `checkout-api`, `user-profile-service`, `ios-app`.
- **Pros**: Creates a very clear link between a flag and the codebase it lives in. Ideal for technical flags that control infrastructure, performance, or kill switches.
- **Cons**: Can be confusing for user-facing features that involve changes across multiple services, as a single product feature might require coordinating flags across several projects.

**By product line or business unit**

In larger enterprises, it often makes more sense to align projects with broader business contexts rather than individual engineering teams.
In this setup, it's important to use a clear system for tags indicating granular ownership, for example `team:checkout`, `app:ios`.

- **Project name**: `enterprise-accounts`, `consumer-banking`, `insurance-products`.
- **Pros**: Aligns feature management with business-level objectives and scales well in very large organizations.
- **Cons**: Requires discipline in applying tags consistently to indicate clear ownership.

**By initiative or temporary project**

Sometimes, a group of features is part of a single, time-bound initiative, like a major redesign or a new market launch.
- **Project name**: `project-phoenix-redesign`, `new-market-latam`.
- **Pros**: Keeps all flags related to a specific initiative in one place, making it easy to archive or clean up once the project is complete.
- **Cons**: Flags might need to be moved to a more permanent project if they persist after the initiative ends.

**Hybrid**

If you find that adhering to a single, rigid model isn't the right fit, consider a hybrid approach that combines some of these strategies to fit your needs.
A common pattern is to have projects for individual teams alongside shared projects for cross-functional work.

For example, your setup might look like this:

- **Team projects**: `payments-squad` and `user-profile-team` have their own projects for day-to-day work.
- **Shared projects**: A `shared-mobile` project exists for features that require coordination between the iOS and Android teams.
- **Operational projects**: A central `platform-operations` project holds critical kill switches or infrastructure flags managed by a dedicated SRE or platform team.

This hybrid structure provides both clear ownership for autonomous teams and the necessary flexibility for collaboration and central governance.

### Handling cross-application features
A common challenge is managing a single feature that spans multiple services (for example, a frontend application and a backend API). You have two primary strategies:

- **Use a single, shared flag**: If the services are implementing parts of the same logical feature that must be released and enabled together, they should share a single flag from one project. This ensures consistency and acts as a single switch for the entire feature.
- **Use separate, coordinated flags**: If the services are owned by different teams and have different release cadences, it's better to create separate flags in their respective projects. This prevents one team from impacting another's release. The rollout can then be coordinated across teams using release templates.

## Evolve your structure
Remember that your initial project and environment structure is not set in stone. Unleash is flexible. You can add new environments, create new projects, and even move flags between them later. For larger migrations, you can use the [Import/Export](/how-to/how-to-environment-import-export) functionality or the [Admin API](/api-overview).

The system is designed to evolve with your organization, so don't be afraid to start with a simple setup and refactor as your needs change.

## Design for collaboration and visibility

Modern applications are composed of multiple services with many complex dependencies. While organizing flags into projects is a good starting point, your feature management system should be open by default.

An engineer on the `user-profile-service` team might need to investigate a bug that depends on a flag in the `checkout-api` project.
When someone searches for a flag, they should be able to view its configuration and ownership so they can request access or submit a change request.

This transparency is key to debugging complex, cross-service interactions. Unleash supports private projects, but these should be the exception, not the norm.

## Secure your setup

Once you have a logical structure for your projects and environments, you can secure it using Unleash's [role-based access control](/reference/rbac) (RBAC) framework. RBAC allows you to implement the principle of least privilege, ensuring users only have the access they need.

Unleash provides two levels of access control:
- **Root roles**: These roles (Admin, Editor, Viewer, or custom) grant permissions across the entire Unleash instance for global resources like users, groups, SSO configurations, and instance-wide settings.
- **Project roles**: These roles (Owner, Member, or custom) grant permissions within a specific project. This is where you implement the most granular day-to-day access controls for your development teams.

### Environment-specific permissions

A key capability for enterprise governance is the ability to define [custom project roles](/reference/rbac#custom-project-roles) with [environment-specific permissions](/reference/rbac#root-permissions). This allows you to precisely control what actions a user can take in each environment.
For example, you can create a "Developer" role that allows a team member to freely create and modify activation strategies in the `development` environment but only allows them to submit a change request for the `production` environment.
This workflow empowers developers to innovate quickly in safe environments while ensuring that all changes to production are subject to a formal review and approval process.

| Role            | Permissions in development                               | Permissions in test                                       | Permissions in production                                                   | Rationale                                                                                                                                          |
|-----------------|----------------------------------------------------------|-----------------------------------------------------------|-----------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| Developer       | Full access to create/update/delete strategies and flags | Full access to enable/disable flags and update strategies | Read-only access and submit change requests                                | Allows developers to iterate quickly in their own environment while ensuring changes to production environments are controlled and reviewed        |
| QA Engineer     | Read-only access                                         | Full access to enable/disable flags and update strategies | Read-only access                                                            | Empowers the QA team to fully control feature configurations in their dedicated testing environment without affecting development or production    |
| Product Manager | Read-only access                                         | Read-only access                                          | Can enable/disable flags and update rollout percentages via change requests | Allows product managers to control the business logic of a release (e.g., gradual rollouts) in production through a safe, audited approval process |
| DevOps/SRE      | Full access                                              | Full access                                               | Full access                                                                 | Enables platform owners to manage all aspects of the feature flagging system, including acting as kill-switch operators in case of an incident     |

### Automating at scale with SSO and SCIM

For large organizations, manually managing user accounts and permissions isn't scalable. Unleash integrates with your existing identity provider (like Okta, Microsoft Entra ID, or Keycloak) via SAML or OpenID Connect for [single sign-on](/reference/sso) (SSO).

Furthermore, Unleash supports the [SCIM protocol](/reference/scim), which automates the provisioning and de-provisioning of users and the syncing of user groups.

This ensures that a user's access to Unleash is always in sync with their status in your central identity management system, significantly improving security and reducing administrative overhead.

### Security for API tokens

Security is enforced through [API tokens](/reference/api-tokens-and-client-keys) that are scoped to a specific environment and one or more projects. This allows you to apply the principle of least privilege to your applications.

For example, your checkout service would use a token valid only for the `production` environment and the `project-checkout`. This token could not fetch configurations from the `development` environment, nor could it access flags from another project like `project-search`.
This creates a strong security boundary, serving as a critical safeguard against both environment mix-ups and unauthorized cross-project data access.

As with any API token, proper secret management is essential to prevent misuse.

## Manage flag configurations across projects and environments

With a secure and logical structure in place, you can focus on managing flag configurations efficiently.

### Strategy variants
[Strategy variants](/reference/strategy-variants), used for A/B testing, are configured as part of an activation strategy within a specific environment.
This powerful scoping means you can run a complex experiment with multiple variants in your production environment while the same feature flag has a simple on/off strategy in your development environment.
This allows for safe, targeted experimentation without impacting other stages of your lifecycle.

### Segments

Segments are reusable collections of strategy constraints and are one of the most powerful tools for managing configurations at scale. Rather than adding dozens of constraints to every flag, you can define a complex audience once and reuse it everywhere.

Imagine you want to target "Power Users in Europe". Instead of adding multiple constraints to every flag for this group, you can create a single `PowerUsers-Europe` segment with the definition:

- `region is one of ['DE', 'FR', 'UK', 'ES']`
- **AND** `subscriptionTier is one of ['pro', 'enterprise']`

Now, you can simply apply this one segment to all relevant feature flags. If you later decide to add Italy to your definition of Europe, you update the segment in one place, and the change instantly propagates to every flag that uses it.

This reduces redundant configuration, minimizes human error, and makes managing large user groups effortless. Segments can be global (available to all projects) or project-scoped.

### Release templates

To ensure consistency in how you roll out features, you can use [release templates](/reference/release-templates).
A release template is a pre-defined set of milestones for different environments. For instance, you could create a "Gradual Rollout UK" template that automatically configures a new flag to be:

- **On** for everyone in `development`.
- **On** only for the `QA Engineers` segment in `testing`.
- **Enabled** for 10% of users in the UK in `production`.

![Example of progressive milestones](/img/progressive-milestones.png)

Using release templates saves time, reduces manual errors, and ensures that all teams follow a standardized and proven rollout process for common release patterns.

### Flag dependencies

Unleash allows you to create [parent-child dependencies](/reference/feature-toggles#feature-flag-dependencies) between flags, ensuring a child flag can only be enabled if its parent is also enabled.
A critical architectural constraint is that dependent flags must belong to the same project.

This constraint is intentional and crucial for preventing architectural fragility. If a flag in `project-search` could depend on a flag in `project-payments`, the Search team could inadvertently break the Payments feature.
This creates hidden, cross-team dependencies that are difficult to track and debug. By keeping dependencies within a single project, ownership and impact remain clear and contained.

### Cloning environments

Unleash Enterprise allows you to [clone an entire environment](/reference/environments#clone-an-environment), which duplicates the environment along with all its feature flag configurations. This is useful for setting up new environments quickly, but it also enables advanced workflows.
For a complex launch, you could clone your production environment to create a temporary `release-rehearsal-q4` environment.

In this isolated space, the team can practice the exact release sequence, validating dependencies and system behavior without any risk to live systems.

## Best practices for long-term maintenance

A feature flagging system requires good housekeeping to remain effective and avoid accumulating technical debt.

### Establish naming conventions

A consistent naming convention is crucial for clarity. A good name should make a flag's purpose immediately obvious.
Because flag names must be unique across the entire Unleash instance, plan a convention that ensures uniqueness.

To ensure these conventions are followed, Unleash allows you to [enforce a specific naming pattern](/reference/feature-toggles#set-a-naming-pattern) at the project level.
For example, in `project-checkout`, you could require all new flags to follow the pattern `checkout-[feature-name]`. Any attempt to create a flag with a non-compliant name will be rejected.
This is a key governance tool for preventing a chaotic and inconsistent flag namespace as your organization grows.

### Use tags for discovery and automation

[Tags](/reference/feature-toggles#tags) are free-form labels that you can apply to feature flags to add flexible, cross-project metadata. 

You can use tags to:
- **Filter and search**: "Show me all flags tagged with team:payments."
- **Indicate ownership**: "Who is the point of contact for this flag? Check the owner:jane.doe@example.com tag."
- **Drive automation**: Configure integrations. For example, you can post a Slack notification for any updates to flags tagged with `slack-channel:checkout-alerts`.

Use colors in tags to add further visual distinctions and make flags easy to identify at a glance.

### Mandate approvals and audit everything

For critical environments like production, enable [change requests](/reference/change-requests) to enforce a "four-eyes principle", where one user proposes a change and another must approve it. This is essential for compliance and preventing costly mistakes.

Equally important is tracking what happens to your flags. In Unleash, [Event Log](/reference/events) provides accountability, simplifies debugging, and is indispensable for security and compliance.

### Archive and clean up stale flags

Ensure that your teams have a clear and [effective process](/feature-flag-tutorials/use-cases/manage-feature-flags-in-code#flag-cleanup-best-practices) for cleaning up stale feature flags to avoid accumulating [technical debt](/reference/technical-debt).
Use [feature flag lifecycle data](https://www.getunleash.io/blog/feature-lifecycle-management) from Unleash to improve your workflows over time.

## Key takeaways

By following these best practices, you can harness Unleash to bring order and scalability to your feature management. A well-designed system leads to a more secure, collaborative, and efficient rollout process for all your features.

Remember these core principles:

- **Structure follows strategy**: Align your projects with your team structure (for example, by team, application, or business unit).

- **Environments map to your deployment pipeline**: Create environments that mirror your actual release stages.

- **Embrace the unified model**: Manage one flag across its entire lifecycle for a single source of truth.

- **Secure by design**: Use RBAC, environment-specific permissions, and SSO to enforce the principle of least privilege.

- **Maintain clarity and auditability**: Enforce naming conventions, use tags, require approvals, and audit everything to prevent technical debt.

## Frequently asked questions (FAQs)

**How can we synchronize flag configurations between different environments?**

For your day-to-day workflow, you typically configure the flag's activation strategies in each of the target environments manually.
If you want to bootstrap a whole new environment, you can clone an existing environment and tweak the flag configurations as needed.
For full automation, you can use the Unleash API to build scripts that read the configuration from a source environment and apply it to a target.

**Can I restrict a user's access to only one environment within a project?**

Yes. This is a core use case for custom project roles. You can create a new role (for example, "QA Engineer") and grant it permissions, such as `UPDATE_FEATURE_STRATEGY`, only for the testing environment. For all other environments like development and production, you would grant no permissions or read-only permissions. This ensures the user can only make changes in their designated environment.

**How many environments should we have?**

It depends on your release process. A typical setup for a large organization is three to five environments:
- development: For local developer machines and CI builds.
- test or QA: A shared, stable environment for dedicated testing by the QA team.
- staging or pre-prod: A production-like environment for final validation, performance testing, and release rehearsals.
- production: The live environment for your end users.

Some organizations add more specialized environments, such as one for demo purposes or a hotfix environment for emergency patches.

**How is Unleash's environment model different from other tools like LaunchDarkly?**

Unleash uses a unified flag model where a single flag is a persistent entity across all environments, with only its configuration (strategies, variants) changing per environment. This provides a holistic, end-to-end view of a feature's lifecycle from a single dashboard.

Other tools may treat flags in each environment as more distinct, separate objects, which can sometimes make it harder to trace a single feature's entire journey. The key benefit of the Unleash model is simplified management, clear traceability, and a more intuitive structure for applying environment-specific RBAC.

**How many projects should we create?**

Start with a structure that mirrors how your teams are organized. Avoid the extremes of a single monolithic project or a separate project for every feature.
A good rule of thumb is to create projects for distinct, long-lived teams, products, or applications. You can always refactor later.

**Can a single feature flag exist in multiple projects?**

No. A feature flag belongs to exactly one project. This is fundamental to Unleash's model, as the project defines the flag's ownership and access control.

**We are a small team just starting out. What's a good initial setup?**

Start simple. Use a single project named after your main application or team. Within that project, use the two default environments: `development` and `production`. This provides the essential separation and is easy to manage.
You can add more environments or projects as you grow.

**How do we handle flags that are used in multiple services or applications?**

This is a strength of a centralized system. If multiple services need to check the same flag, they can all use the same Unleash project and environment API key. However, it doesn't always make sense for different services to share flags.
- When to use a single flag: If multiple services are implementing parts of the same logical feature that must be released together, they should share a single flag from one project. This ensures consistency.
- When to use separate flags: If the services are owned by different teams and have different release cadences, or if the functionality is related but not tightly coupled, it's better to create separate flags in their respective projects. This prevents one team from impacting another's release.

**What if a team needs a new environment or project later on?**

Unleash is flexible. You can add new environments at any time and decide which projects they apply to. You can also create new projects and even move flags between them if their environment setups are compatible. The system is designed to evolve with your organization, so don't be afraid to refactor your setup as your needs change.

**What's the best way to handle a feature that spans multiple projects?**

First, evaluate your project boundaries. If the features are tightly coupled and must be released together, they might belong in the same project. If they are separate but need coordination, the best practice is to create separate flags in each project and coordinate their rollout manually or through external automation. This respects project boundaries and avoids creating hidden, complex dependencies.

**Can we manage our Unleash setup using Infrastructure as Code tools like Terraform?**

Yes, and it is a highly recommended practice for ensuring consistency and automation at scale. Unleash has a Terraform Provider that allows you to manage your instance configuration—things like projects, environments, segments—as code.

This brings your feature flag configuration into a Git workflow, enabling version control, peer reviews, and automated, repeatable deployments. It's a powerful approach for platform and DevOps teams looking to manage Unleash at scale.