Cross-Project Dependencies #
Quad-Ops supports declaring dependencies on services in other projects using the x-quad-ops-depends-on extension field. This enables complex multi-project architectures where services can depend on infrastructure or platform services deployed separately.
Overview #
Use Cases:
- Shared Infrastructure - Application services depend on centrally-managed databases or message queues
- Service Mesh - Multiple projects route through a shared ingress proxy
- Platform Services - Applications depend on monitoring, logging, or observability infrastructure
- Microservice Dependencies - Services in different projects that communicate with each other
Syntax #
Add the x-quad-ops-depends-on extension field to any service:
services:
backend:
image: myapp:latest
x-quad-ops-depends-on:
- project: infrastructure
service: proxy
optional: false # Default: fail if not found
- project: monitoring
service: prometheus
optional: true # Warn if not found
Fields #
- project (required) - Name of the other project (must follow project naming rules)
- service (required) - Name of the service in that project (must follow service naming rules)
- optional (optional, default: false) - If true, warns when missing; if false, deployment fails
How It Works #
1. Validation #
When you run quad-ops up or quad-ops sync, Quad-Ops:
- Parses the
x-quad-ops-depends-onfield from your compose file - Validates that external services exist in the runtime (systemd or launchd)
- Required dependencies - Fails deployment with clear error if missing
- Optional dependencies - Logs warning if missing but continues deployment
2. Startup Ordering #
External dependencies are included in the topological ordering graph:
infrastructure-proxy.service (deployed in infrastructure project)
↓ (After + Requires)
app-backend.service (this project)
Services start in dependency order, ensuring external dependencies are running before dependent services.
3. Platform Integration #
Linux (systemd/Quadlet):
[Unit]
Description=app-backend container
After=infrastructure-proxy.service
Requires=infrastructure-proxy.service # or Wants= for optional
macOS (launchd):
<key>DependsOn</key>
<array>
<string>com.quad-ops.infrastructure.proxy</string>
</array>
Complete Example #
Step 1: Deploy Infrastructure Project #
# ~/projects/infrastructure/compose.yml
name: infrastructure
services:
proxy:
image: nginx:latest
ports:
- "80:80"
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
cd ~/projects/infrastructure
quad-ops up
# Creates: infrastructure-proxy.service, infrastructure-db.service
Step 2: Deploy Application Project with External Dependencies #
# ~/projects/myapp/compose.yml
name: myapp
services:
backend:
image: myapp:latest
x-quad-ops-depends-on:
- project: infrastructure
service: proxy
- project: infrastructure
service: db
depends_on:
- redis # Intra-project dependency
redis:
image: redis:latest
cd ~/projects/myapp
quad-ops up
# 1. Validates infrastructure-proxy and infrastructure-db exist
# 2. Generates myapp-backend.container with After=/Requires= for external deps
# 3. Starts in order: infrastructure-proxy, infrastructure-db → myapp-redis → myapp-backend
Step 3: Updates Cascade Automatically #
When infrastructure services restart, dependent services automatically restart (via systemd Requires=):
cd ~/projects/infrastructure
git pull
quad-ops sync
# infrastructure-proxy restarts → systemd auto-restarts myapp-backend
Optional Dependencies #
Use optional: true for graceful degradation when external services might not be available:
services:
app:
image: myapp:latest
x-quad-ops-depends-on:
- project: monitoring
service: prometheus
optional: true # Warn if missing, don't fail
Behavior:
- If
monitoring-prometheusexists: AddsAfter+Wants(soft dependency) - If
monitoring-prometheusmissing: Logs warning, continues deployment
When to use optional dependencies:
- Development/testing environments where monitoring isn’t deployed
- Graceful degradation scenarios
- Feature flags that enable/disable integrations
Naming Requirements #
External project and service names must follow the same naming rules as regular names:
Project names: ^[a-z0-9][a-z0-9_-]*$
- Must start with lowercase letter or digit
- Can contain: lowercase letters, digits, dashes, underscores
Service names: ^[a-zA-Z0-9][a-zA-Z0-9_.-]*$
- Must start with alphanumeric character
- Can contain: alphanumeric, dashes, underscores, periods
Invalid names will cause validation errors with clear messages.
Limitations #
Same User/System Scope #
External dependencies must be in the same scope (user vs system):
- ✅ User service → User service (both rootless)
- ✅ System service → System service (both root)
- ❌ User service → System service (cross-scope not supported by systemd)
No Circular Dependencies #
Circular dependencies across projects are not allowed:
project-a (service: api) → project-b (service: db)
↓
project-b (service: cache) → project-a (service: auth)
This creates a cycle and will fail deployment. Design your architecture to avoid circular dependencies.
Deployment Order Matters #
External services must be deployed before dependent projects:
- Deploy
infrastructureproject first (quad-ops up) - Then deploy
appproject that depends on it
If you try to deploy app first, validation will fail with:
Error: required external service not found: infrastructure-proxy
Ensure projects are deployed in correct order
Troubleshooting #
Error: “required external service not found” #
Cause: The external service hasn’t been deployed yet.
Fix: Deploy the dependency project first:
cd ~/projects/infrastructure
quad-ops up
cd ~/projects/myapp
quad-ops up # Now succeeds
Error: “invalid project name” in x-quad-ops-depends-on #
Cause: Project name doesn’t follow naming requirements.
Fix: Update to use valid project name matching ^[a-z0-9][a-z0-9_-]*$:
# ❌ Invalid
x-quad-ops-depends-on:
- project: My-Infrastructure # Uppercase
service: proxy
# ✅ Valid
x-quad-ops-depends-on:
- project: infrastructure
service: proxy
Warning: “optional external dependency not found” #
Cause: Optional dependency doesn’t exist (this is not an error).
Action:
- If the service should exist, deploy it
- If it’s expected to be missing in this environment, no action needed
Best Practices #
- Deploy dependencies first - Always deploy infrastructure/platform projects before dependent applications
- Use optional wisely - Only mark dependencies as optional if your app can truly function without them
- Document dependencies - Add comments in compose files explaining why external dependencies exist
- Consistent naming - Use consistent project naming across your infrastructure
- Separate concerns - Group related infrastructure services in dedicated projects
See Also #
- Docker Compose Support - Full list of supported Compose features
- Repository Structure - Organizing multiple projects
- Naming Requirements - Project and service naming rules