Skip to main content Skip to content

Projects and environments

How ZopDay organises deployments into projects and environments; the catalog hierarchy that drives everything else.

6 min read Last updated: 

ZopDay’s deployment catalog is a three-level hierarchy: Project → Environment → Deployment. Get this right at the start and the rest of the product slots in around it cleanly. Get it wrong and you’ll be reshuffling for weeks.

ZopDay Projects list with payment-service, user-dashboard, and notification-engine cards, each showing its environment count and health status

The Projects list; each project with its environments and health, the top of the Project → Environment → Deployment hierarchy.

The hierarchy

Terminal window
Organisation
└── Project (org-scoped grouping; usually a service, team, or app)
└── Environment (binds to a space + namespace + registry)
└── Deployment (a git repo + branch + config)
└── Revision (one rollout; built image + Helm release)
LevelOwned byStored asWhat it represents
ProjectOrgCatalogAn org-scoped grouping. Org name + project name is unique.
EnvironmentProjectCatalogThe “where”; a space + namespace + (optional) registry integration.
DeploymentEnvironmentCatalogThe “what”; repo URL, branch, config. Infra fields are inherited from the parent environment.
RevisionDeploymentRuntimeOne rollout. Carries the built image and its rollout state.

The split between catalog and runtime data is deliberate; see the deployments concept page for why.

Projects

A project is the top-level grouping. Org-scoped, soft-deletable, no nesting.

When to create a project

  • One service that has its own repo, owners, and release cadence → one project
  • A monorepo with multiple deployable services → still one project; multiple deployments inside it
  • A platform team’s shared infrastructure (gateways, ingress controllers, observability stack) → its own project, separate from product projects

Project fields

FieldRequiredNotes
nameyesOrg-unique. Used in URLs and as a label. Lowercase kebab-case recommended.
descriptionnoFree-form. Shows on the project list.
canvasPositionno{x, y} finite numbers. Drives layout on the architecture canvas.

Project endpoints

Terminal window
POST /projects Create
GET /projects List with filters
GET /projects/{id} Get one
PATCH /projects/{id} Partial update
DELETE /projects/{id} Soft-delete
GET /projects/{id}/stats Per-project deployment / revision counts

Environments

An environment binds a project to a runnable target. Every deployment lives inside exactly one environment, and the environment provides the infrastructure context.

Environment fields

FieldRequiredNotes
nameyesProject-unique. Common patterns: prod, staging, qa, dev, or preview-{slug}.
space_idyesThe registered Kubernetes cluster. See Cluster registration.
namespaceyesThe Kubernetes namespace inside the space. ZopDay creates it if it doesn’t exist (with the right RBAC).
registry_integration_idnoWhere built images are pushed. If unset, ZopDay uses the cloud-default registry (ECR / Artifact Registry / ACR) on the same cloud account as the space.

Why bind the namespace at the environment level

Because deploys cross-reference each other by environment. If two deployments live in payments-prod (same environment), they can wire up via service connections without specifying a namespace explicitly; the platform knows where to look.

Multiple environments can share a namespace if you really need to (e.g. a staging environment that lives in the same namespace as another project’s staging) but it’s discouraged; you give up isolation guarantees on resource limits, RBAC, and tear-down.

Environment endpoints

Terminal window
POST /projects/{projectID}/environments Create
GET /projects/{projectID}/environments List
GET /environments/{envID} Flat get (no project context needed)
PATCH /projects/{projectID}/environments/{id} Partial update
DELETE /projects/{projectID}/environments/{id} Delete
GET /environments/{envID}/deployments List deployments in this env
POST /environments/{envID}/deployments Create deployment in this env
GET /environments/{envID}/stats Per-env deployment / revision counts

Namespace discovery on the cluster behind an environment is served at GET /space-discovery/{spaceID}/namespaces (it needs a kubeconfig); see Deployment spaces and the API reference for request/response details.

Common patterns

One project per service, multiple environments

The most common shape. Each service is a project; each project has dev, staging, prod environments, each bound to a different cluster (or the same cluster, different namespaces).

Terminal window
payments (project)
├── dev → space: shared-dev-cluster, namespace: payments-dev
├── staging → space: staging-cluster, namespace: payments-staging
└── prod → space: prod-cluster, namespace: payments-prod

One project, many ephemeral environments (preview branches)

Each PR gets its own short-lived environment. Common pattern for review apps.

Terminal window
payments (project)
├── prod → space: prod, namespace: payments-prod
├── staging → space: staging, namespace: payments-staging
├── preview-pr-1234 → space: review, namespace: pr-1234 (auto-created on PR open)
├── preview-pr-1245 → space: review, namespace: pr-1245
└── ...

The preview environments are torn down by automation on PR close; call DELETE /environments/{id} from your CI on the close webhook. Cascading deletion removes the deployment rows and any pending revisions.

Multi-tenant platform team

A platform team running shared services (ingress controllers, observability) keeps them in their own project, bound to a different namespace per cluster.

Terminal window
platform (project)
├── prod → space: prod, namespace: platform-system
└── dev → space: dev, namespace: platform-system

What changes when you change an environment

Two infra fields on the environment can change in place:

ChangeWhat happens
namespaceExisting deployments do not migrate. ZopDay flags a divergence; you can re-deploy each one to land it in the new namespace.
registry_integration_idNew builds push to the new registry. Existing revisions still reference their original image hashes. Re-deploy to pin everything to the new registry.
space_idSame as namespace; flagged but not auto-migrated. Use carefully.

A space_id change is usually a “we’re moving from cluster A to cluster B” event. Coordinate with whoever owns DNS and load balancing on top.

Org cascade

Deleting an organisation cascades, which:

  • Soft-deletes every project owned by the org
  • Soft-deletes every environment inside those projects
  • Soft-deletes every deployment + revision inside those environments
  • Wipes org settings (including default dashboards, default cluster, etc.)

Spaces are not deregistered on org deletion; the underlying cluster is yours, not ZopDay’s. If you also want to remove the cluster-side artefacts, run a teardown per deployment before the org cascade.

Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001 · zero-trust· 30% average cloud cost cut· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001 · zero-trust· 30% average cloud cost cut· 4 platforms · 1 console·