Workload Placement Examples
These worked examples give you copy-ready configurations once you know what you want. For the concepts, configuration components, and field options, see Workload Placement.
Implementation Examples
Optimizing for Cost and Performance
This example creates a cost-optimized infrastructure with dedicated node pools for different workload types.
-
Rack Configuration:
$ convox rack params set additional_node_groups_config=/path/to/node-groups.json -r production $ convox rack params set additional_build_groups_config=/path/to/build-groups.json -r productionNode groups config (AWS):
[ { "id": 101, "type": "t3.medium", "capacity_type": "ON_DEMAND", "min_size": 1, "max_size": 5, "label": "critical-services", "tags": "department=frontend,environment=production,cost-center=web" }, { "id": 102, "type": "c5.large", "capacity_type": "SPOT", "min_size": 0, "max_size": 10, "label": "batch-workers", "tags": "department=data,environment=production,cost-center=analytics" } ]Node groups config (Azure):
[ { "id": 101, "type": "Standard_D4s_v3", "capacity_type": "ON_DEMAND", "min_size": 1, "max_size": 5, "label": "critical-services", "tags": "department=frontend,environment=production,cost-center=web" }, { "id": 102, "type": "Standard_E4s_v3", "capacity_type": "SPOT", "min_size": 0, "max_size": 10, "label": "batch-workers", "tags": "department=data,environment=production,cost-center=analytics" } ]Build groups config (AWS):
[ { "type": "c5.xlarge", "capacity_type": "SPOT", "min_size": 0, "max_size": 5, "label": "app-build" } ]Build groups config (Azure):
[ { "type": "Standard_D8s_v3", "capacity_type": "SPOT", "min_size": 0, "max_size": 5, "label": "app-build" } ] -
Application Configuration:
$ convox apps params set BuildLabels=convox.io/label=app-build -a myapp $ convox apps params set BuildCpu=1000 BuildMem=4096 -a myapp -
Service Configuration (in
convox.yml):services: web: build: . port: 3000 nodeSelectorLabels: convox.io/label: critical-services worker: build: ./worker nodeSelectorLabels: convox.io/label: batch-workers
This configuration creates:
- On-demand nodes for critical services like web frontends
- Spot instance nodes for batch processing workloads
- Separate spot instance nodes optimized for build processes
- Provider tags for accurate cost attribution across teams and environments
Isolating High-Priority Workloads
To create dedicated node groups that exclusively run specific services:
-
Create a JSON file for your node group configuration:
AWS:
[ { "id": 103, "type": "m5.large", "capacity_type": "ON_DEMAND", "min_size": 2, "max_size": 5, "label": "database-workers", "dedicated": true, "tags": "environment=production,team=datastore,criticality=high" } ]Azure:
[ { "id": 103, "type": "Standard_E4s_v3", "capacity_type": "ON_DEMAND", "min_size": 2, "max_size": 5, "label": "database-workers", "dedicated": true, "tags": "environment=production,team=datastore,criticality=high" } ] -
Apply the configuration:
$ convox rack params set additional_node_groups_config=/path/to/dedicated-nodes.json -r production -
Service Configuration (in
convox.yml):services: db-processor: build: ./processor nodeSelectorLabels: convox.io/label: database-workers
With dedicated:true, only services that explicitly select the node group will run on it, ensuring isolation for sensitive workloads.
Mixed ARM/x86 Architecture
This example sets up an x86 primary rack with ARM worker nodes and ARM build nodes, allowing cost-optimized Graviton instances for selected apps while keeping x86 available for compatibility-sensitive workloads.
Mixed architecture support is available on AWS racks running version 3.24.1 or later.
-
Add ARM worker nodes (dedicated so only targeted apps land on them):
[ { "id": 104, "type": "t4g.medium", "capacity_type": "ON_DEMAND", "min_size": 1, "max_size": 5, "label": "arm-workers", "dedicated": true, "tags": "architecture=arm64,environment=production" } ]$ convox rack params set additional_node_groups_config=/path/to/arm-nodes.json -r production -
Add ARM build nodes so ARM apps build natively without emulation:
[ { "id": 201, "type": "t4g.medium", "capacity_type": "ON_DEMAND", "min_size": 1, "max_size": 2 } ]$ convox rack params set additional_build_groups_config=/path/to/arm-build-nodes.json -r production -
Configure each ARM app to build on the correct architecture:
$ convox apps params set BuildArch=arm64 -a myapp -
Target the app to ARM workers in
convox.yml:services: web: build: . port: 3000 nodeSelectorLabels: convox.io/label: arm-workers -
Deploy:
$ convox deploy -a myapp
The build runs on an ARM build node (via BuildArch=arm64), producing a native ARM binary. The resulting pods run on the dedicated ARM worker nodes (via nodeSelectorLabels). Apps without BuildArch continue building and running on x86 nodes as before.
Reverse direction works the same way: if your primary rack uses ARM (e.g., node_type=t4g.medium), add x86 additional groups and set BuildArch=amd64 on apps that need Intel/AMD compatibility.
Key considerations:
BuildArchis per-app, not per-service. Apps with services targeting different architectures should be split into separate apps.- Convox system images (including Fluentd) are multi-arch manifests and run natively on both architectures with no configuration.
- The
kubernetes.io/archlabel is set automatically by the kubelet, so this works on AWS, Azure, and GCP without provider-specific setup.
For full BuildArch parameter details, see BuildArch.
Flexible Configuration Options
Convox allows you to implement different levels of customization based on your needs:
-
Build Isolation Only: Configure only
additional_build_groups_configto isolate build processes while keeping services on standard nodes:$ convox rack params set additional_build_groups_config=/path/to/build-groups.json -r production $ convox apps params set BuildLabels=convox.io/label=app-build -a myapp -
Service Placement Only: Configure only
additional_node_groups_configto customize service placement while letting builds run on standard nodes:$ convox rack params set additional_node_groups_config=/path/to/node-groups.json -r productionIn your
convox.yml:services: web: nodeSelectorLabels: convox.io/label: critical-services -
Complete Workload Management: Implement both configurations for full control over placement of both services and build processes.