# Manage Catalyst Projects

A **Catalyst project** is the top-level container that groups workloads, components, configurations, subscriptions, and managed infrastructure. Each project exposes its own HTTP and gRPC Dapr endpoints, ingress and egress addresses, and role assignments — making projects the main unit of isolation between environments, teams, or applications in Catalyst.

:::tip Manage from the Catalyst console

Every operation on this page — creating projects, selecting them, updating managed services, and deleting them — can also be done from the Catalyst Web UI at [catalyst.diagrid.io](https://catalyst.diagrid.io).

:::

- Logical container — A project groups all Dapr resources (workloads, components, subscriptions, configurations) and provides shared endpoints for the workloads inside it.
- Isolation boundary — Projects have their own network addresses, role scopes, and optionally managed Pub/Sub, Key/Value, and Workflow stores.

## When to create a new project

Use a project to draw an isolation boundary. Common patterns:

- **Per-environment** — separate `dev`, `staging`, and `prod` projects so resources, components, and API keys never cross boundaries.
- **Per-team or per-business-unit** — give each team its own project and scoped roles so they can only manage their own apps.
- **Per-application** — for workloads with stricter isolation requirements (regulated data, tenant-specific infrastructure, or dedicated resiliency policies).

A project lives inside a [Region](https://docs.diagrid.io/operate/platform-operations/regions). On [Catalyst Cloud](https://docs.diagrid.io/operate/hosting/catalyst-cloud) the region is managed by Diagrid; on [Catalyst Enterprise Self-Hosted](https://docs.diagrid.io/operate/hosting/enterprise-self-hosted) you can create and deploy your own regions.

## Create a project

Use the Diagrid CLI to create a project:

```bash
diagrid product use catalyst

# Create a project in the organization's default region
diagrid project create my-project --wait

# Or target a specific region explicitly
diagrid project create my-project --region my-region --wait

# Create a project that opts into the managed Pub/Sub broker and KV store
diagrid project create my-dev-project \
  --deploy-managed-pubsub \
  --deploy-managed-kv \
  --wait
```

Without `--region`, projects are provisioned in the [organization default region](https://docs.diagrid.io/operate/platform-operations/regions#set-the-organization-default-region). On Catalyst Cloud the default is managed by Diagrid; on Catalyst Enterprise Self-Hosted you set it yourself with `diagrid region use` — creating a region does not auto-set it.

See [`diagrid project create`](https://docs.diagrid.io/references/catalyst/cli-reference/project/create) and [`diagrid product use`](https://docs.diagrid.io/references/catalyst/cli-reference/product) for the full flag set.

A project can also be created in a [region group](https://docs.diagrid.io/operate/platform-operations/multi-region) instead of a single region. It is then placed in every member region and keeps one set of hostnames, so it survives the loss of a region without its applications changing anything. You make the choice once: a project belongs either to a group or to a region, and cannot be moved between them.

:::tip Managed infrastructure

Managed Pub/Sub, Key/Value, and Workflow stores are hosted by Catalyst and available as backing infrastructure for development without provisioning your own. See [Managed services](https://docs.diagrid.io/operate/project-operations/managed-services).

:::

## Inspect a project

Every project exposes the network details your applications need to connect:

```bash
diagrid project get my-project
```

See [`diagrid project get`](https://docs.diagrid.io/references/catalyst/cli-reference/project/get) for output formats. The output includes:

- **HTTP endpoint** and **gRPC endpoint** — the URLs your Dapr SDKs should point at.
- **Ingress address** — the public network address of the Catalyst Data Plane for this project.
- **Egress address** — the source IP address Catalyst uses when calling back into your applications. If your app lives behind a firewall, this is the IP you need to allow. Add it to your firewall, API gateway, or load balancer allowlists.
- **Region** — the region hosting the project.
- **Managed services status** — whether the managed Pub/Sub, KV, or workflow stores are enabled.

See the [Connect to Catalyst](https://docs.diagrid.io/develop/connect) guide for how these values are used.

## Select the active project

Most Diagrid CLI commands operate on a currently selected project. Set it with:

```bash
# List all projects in the org
diagrid project list

# Select the active project for subsequent commands
diagrid project use my-project
```

See [`diagrid project list`](https://docs.diagrid.io/references/catalyst/cli-reference/project/list) and [`diagrid project use`](https://docs.diagrid.io/references/catalyst/cli-reference/project/use).

You can also target a specific project per command with `--project`:

```bash
diagrid app list --project my-staging-project
```

## Update a project

Update managed infrastructure or other project settings:

```bash
# Enable the managed workflow store on an existing project
diagrid project update my-project --enable-managed-workflow --wait
```

The managed Pub/Sub broker and key-value store are provisioned at creation time with `--deploy-managed-pubsub` and `--deploy-managed-kv` on [`diagrid project create`](https://docs.diagrid.io/references/catalyst/cli-reference/project/create); `diagrid project update` does not accept those flags.

See [`diagrid project update`](https://docs.diagrid.io/references/catalyst/cli-reference/project/update) for the full flag set.

## Delete a project

Deleting a project tears down all apps, components, subscriptions, and managed infrastructure inside it. Make sure no workloads still depend on the project before deleting.

```bash
diagrid project delete my-project --wait
```

See [`diagrid project delete`](https://docs.diagrid.io/references/catalyst/cli-reference/project/delete).

## Scoping roles to a project

Catalyst supports both global and project-scoped roles. Use project-scoped roles to let a developer team manage only their own project without granting access to the entire organization:

```bash
# Editor role scoped to a single project
diagrid apikey create --name dev-team-key \
  --role cra.diagrid:editor:projects:my-dev-project \
  --duration 2592000
```

See [`diagrid apikey create`](https://docs.diagrid.io/references/catalyst/cli-reference/apikey/create) for the full role syntax and examples.

See [Manage Access](https://docs.diagrid.io/operate/platform-operations/identity-and-access#user-roles) for the full list of roles and [API keys](https://docs.diagrid.io/operate/platform-operations/identity-and-access#api-keys) for scoping patterns.

## Enable verifiable execution

[Verifiable execution](https://docs.diagrid.io/concepts/verifiable-execution) cryptographically signs every event in a workflow's history, giving you a tamper-evident record that can be independently verified. Because signing builds on the workload identity and mTLS that Catalyst provides by default, there is nothing to configure in your application code — you enable it on the project, and it applies to every workflow that runs there:

```bash
# Workflow history signing can only be enabled at project creation
diagrid project create payments --enable-workflow-history-signing --wait
```

Signing is a permanent commitment for the workflows created under the project: a signed workflow must always run on signing-enabled infrastructure, you cannot retroactively sign an existing unsigned workflow, and disabling signing would prevent already-signed histories from loading. The signing adds negligible CPU cost, though the extra signature and certificate data increases the storage each workflow step consumes.

See [`diagrid project create`](https://docs.diagrid.io/references/catalyst/cli-reference/project/create) for the full flag set.

### Configure the workflow state store

Signed workflow histories are persisted in the project's workflow state store, and you choose that store when you set the project up:

- **Managed workflow store** — a project created as a **Development environment** in the Catalyst console includes the managed Diagrid components; with the CLI, add `--enable-managed-workflow`. Nothing else to configure; see [Managed services](https://docs.diagrid.io/operate/project-operations/managed-services#workflow-store).
- **Your own state store** — a **Non-development environment** project includes no managed components: you register a transactional state store that you operate (Redis, PostgreSQL, or another [supported store](https://docs.diagrid.io/references/catalyst/components-reference/intro)) as a component yourself, and the workflow engine persists signed histories there.

To bring your own store:

1. Create the project without the managed workflow store — in the console, select **Non-development environment** and turn on **Workflow history signing**; with the CLI, omit `--enable-managed-workflow`:

   ![Create project dialog selecting Non-development environment with the Workflow history signing toggle](https://docs.diagrid.io/img/catalyst/wf-byo-project-create.png)

   ```bash
   diagrid project create payments --enable-workflow-history-signing --wait
   ```

2. Register your state store as a `state` component with the `actorStateStore` metadata field set to `true` — this is what designates it as the store backing the workflow engine.

   In the Catalyst console, open the project's **Components** section and create the component. Pick the **State** type, then a store whose card shows the **Workflow** capability — Redis, for example:

   ![Component catalog marking each state store's Workflow support](https://docs.diagrid.io/img/catalyst/wf-byo-component-type.png)

   In **Assign access**, select the workflow apps that may use the store — access is unrestricted by default:

   ![Assign access step scoping the component to selected apps](https://docs.diagrid.io/img/catalyst/wf-byo-component-access.png)

   In **Authentication profile**, choose how to authenticate against the store and enter the credentials — for Redis, a username and password. Sensitive fields are extracted into the managed secret store, never persisted in plaintext:

   ![Authentication profile step with the Redis username and password fields](https://docs.diagrid.io/img/catalyst/wf-byo-component-auth.png)

   Then, in **Configure component**, name the component, enter the store's connection details — `redisHost` for Redis — and add the **actorStateStore** option with its toggle enabled:

   ![Configure component step with the actorStateStore toggle enabled](https://docs.diagrid.io/img/catalyst/wf-byo-component-configure.png)

   Review the spec in **Preview and save** and create the component.

   The CLI equivalent, with your own Redis:

   ```bash
   diagrid component create workflow-store \
     --type state.redis \
     --metadata redisHost=my-redis.internal:6379 \
     --metadata redisPassword=<password> \
     --metadata actorStateStore=true \
     --scopes order-workflow \
     --wait
   ```

   See the [Redis state store reference](https://docs.diagrid.io/references/catalyst/components-reference/state/redis) for the full metadata, and [Components](https://docs.diagrid.io/operate/project-operations/components) for scoping and secret handling.

A project has exactly one workflow state store: you cannot create an `actorStateStore=true` component while the managed workflow store is enabled, and you cannot create a second one. Signing makes tampering detectable, but it does not protect against data loss — so operate the store with the durability and backups the audit trail warrants.

## Limits and quotas

Limits apply to the resources a project contains — the number of workloads, components, pub/sub subscriptions, managed service data size, and request rate. They are counted **per region**, not per project: each region maintains its own independent quotas, so resources in different regions don't affect each other's limits. Cloud regions have lower limits than dedicated or BYOC regions — compare the [limits per Catalyst Cloud region](https://docs.diagrid.io/operate/plans-and-support#per-catalyst-cloud-region) with the [limits per dedicated or BYOC region](https://docs.diagrid.io/operate/plans-and-support#per-dedicated-or-byoc-region).

The request-rate limit applies per App ID, and body-size limits are set per app — see [Manage IDs](https://docs.diagrid.io/operate/project-operations/ids) for the `--max-body-size` flag and related controls.

## What's next

- [Manage IDs](https://docs.diagrid.io/operate/project-operations/ids) — register workloads inside a project.
- [Manage Components](https://docs.diagrid.io/operate/project-operations/components) — wire up backing infrastructure.
- [Managed services](https://docs.diagrid.io/operate/project-operations/managed-services) — use built-in Pub/Sub, KV, and Workflow stores.
- [Connect to Catalyst](https://docs.diagrid.io/develop/connect) — project endpoints, apps, and callbacks.
