Workspaces
A workspace allows you to manage multiple independently-deployable applications within a single repository. Each application in the workspace maintains its own codebase, fluffy-chainsaw.yaml configuration, and Pulumi infrastructure stack, but they can be deployed and validated together.
The Workspace Manifest (fluffy-chainsaw.workspace.yaml)
A workspace is defined by a fluffy-chainsaw.workspace.yaml manifest at the root of your repository: a defaults: block of deploy parameters shared by every child, and a children: list of the apps themselves. Each child names its directory and may override any default:
# fluffy-chainsaw.workspace.yaml
defaults:
stack: dev
region: us-central1
project: my-project
children:
- dir: examples/auth/app
select: auth # Pulumi program lives at infra/auth
- dir: examples/realtime/live
select: realtime-live
- dir: docs-site/app # no select: the app dir is its own program dir
Manifest Rules
- Paths: Child
dirpaths can be absolute or relative to the directory containing the manifest file. - Order Matters: Deployment runs sequentially in the order listed. If one child application owns a shared resource (like a database or user pool) and other children reference it, the owner application must be listed and deployed before its consumer applications.
- Precedence: each child's parameters resolve as manifest
defaults:< the child app's owndeploy:block in itsfluffy-chainsaw.yaml< the manifestchildren[]entry. An app that declaresstacks:resolves its per-stack values for the child's effective stack (entrystack:> the app'sdeploy.stack>defaults.stack), so per-stack projects and sizing work identically under workspace and standalone deploys. A child with noregion/projectfrom any of the three layers fails before anything deploys. - Pinning is the app's contract, not the manifest's: whether a stack deploys release-pinned digests comes only from
deploy.pinnedin the child's ownfluffy-chainsaw.yaml— the manifest cannot override it.
Deploying a Workspace
To deploy the entire workspace, run the workspace command from the directory containing your manifest:
fluffy-chainsaw workspace deploy
This sequentially builds, provisions, and deploys each child application exactly as if you ran cd <child> && fluffy-chainsaw deploy.
CLI Flags
-config <path>: Specify a custom manifest file path (defaults tofluffy-chainsaw.workspace.yamlin the current directory).-only <child1>,<child2>: Deploy only a subset of children listed in the manifest.
Safety & Resource Ownership
Pulumi isolates stack state per child, meaning one child's deploy cannot naturally modify or destroy another child's resources. However, configuration errors can lead to double ownership (where two applications attempt to manage the same physical resource, leading to collision or accidental deletion during cleanup).
The "One Owner, Many Readers" Rule
To share a resource (like a database, bucket, or user pool) safely:
- Exactly one application must own the resource (declared normally in its
fluffy-chainsaw.yaml). - All other applications referencing the resource must mark it with
existing: truein their configuration.
Double Ownership Validation (E_WORKSPACE_DOUBLE_OWNERSHIP)
Before any deployments are initiated, fluffy-chainsaw workspace deploy performs a static validation pass over all manifest children (including those skipped via -only).
If two applications attempt to own the same physical resource (such as a bucket or database with the same global/project name without existing: true), the deployment fails immediately with E_WORKSPACE_DOUBLE_OWNERSHIP before touching any cloud resources.
Multi-App Firebase Patterns
When deploying multiple applications to a shared Firebase project, use the following configuration patterns to avoid resource collisions:
1. Firebase Hosting (hosting)
By default, Firebase Hosting deploys to the project's default site. To host multiple frontends in one project:
- Declare a
hostingblock with a uniquesiteID in each child'sfluffy-chainsaw.yaml:hosting: site: my-app-frontend - This provisions a non-default Hosting site via Pulumi and configures a shared
firebase.jsonand.firebasercat the workspace root to route and deploy frontends to their correct sites.
2. Realtime Database (realtime.instance)
By default, the realtime plugin connects to the project's default database instance. To deploy multiple realtime apps:
- Name a custom instance under
instancein your child's configuration:realtime: engine: firebase instance: my-app-rtdb
3. Firebase Auth (auth.existing)
To share a single Firebase Authentication user pool across multiple applications in the same project:
- Have exactly one child application declare the auth config:
auth: router: api-runner - Have all other applications consume the pool by marking it as existing:
auth: existing: true router: sibling-api-runner