Parallel Execution

Understand how Runner executes packages in parallel using DAG-based dependency resolution and Data references.

Overview

Bluebricks Runner uses a DAG (Directed Acyclic Graph) to determine package execution order. Packages execute in parallel when possible, with dependencies resolved through Data references that link package outputs to inputs.

This approach enables:

  • Efficient execution - Independent packages run concurrently

  • Output-driven deployment - Only deploy what's needed downstream

  • Clear dependency tracking - Explicit relationships between packages

  • Automatic ordering - Runner determines optimal execution sequence

Data References

What Are Data References?

Data references allow packages to use outputs from other packages as inputs:

Data.<packageId>.<outputKey>

Components:

  • Data. - Reserved prefix for cross-package references

  • <packageId> - Unique ID of the source package

  • <outputKey> - Name of the output from source package

Example:

In this example:

  • eks_cluster depends on vpc_module

  • Runner executes vpc_module first

  • vpc_id and private_subnet_ids outputs flow to eks_cluster inputs

Data References in Expressions

Data references can be used in expressions with other values:

Runner evaluates these expressions at runtime after dependencies complete.

Plan vs Apply Resolution

Data references behave differently during plan and apply:

During Plan:

  • Shows that value will change

  • Indicates value will be available after execution

  • Dependencies identified but values not yet calculated

During Apply:

  • Actual values resolved

  • Passed to dependent packages

  • Used in expressions and property resolution

DAG Structure

Dependency Graph

Runner builds a DAG (Directed Acyclic Graph) representing package relationships:

How it works:

  • Identifies all packages in blueprint

  • Analyzes Data references to find dependencies

  • Creates execution order that respects dependencies

  • Executes packages when their dependencies complete

  • Passes outputs to dependent packages

Example DAG

Consider this blueprint structure:

Resulting DAG:

Execution order:

  1. launch_template executes (no dependencies)

  2. s3_bucket and conditional_resources execute in parallel (both depend only on launch_template)

Output-Driven Execution

Only Deploy What's Needed

Runner only executes packages whose outputs are required downstream:

Example:

Execution:

  • vpc_module EXECUTES (output referenced in outs)

  • monitoring_module SKIPS (output not referenced anywhere)

This ensures:

  • Efficient execution - No unused resources deployed

  • Clear dependency tracking - DAG only includes what's needed

  • Proper resource management - Resources created only if used

Conditional Execution

Use expressions to conditionally execute packages:

If enable_logging is false:

  • Package may still execute (depends on internal logic)

  • But output can conditionally return different values

Data Flow Pattern

Props Flow Down, Data Flows Up

Bluebricks uses a hierarchical data flow model:

Props (Properties):

  • Flow DOWN from parent to child packages

  • Set at deployment time

  • Referenced with Props.<key>

Data (Outputs):

  • Flow UP from child packages to parent

  • Calculated at runtime

  • Referenced with Data.<packageId>.<key>

Example Flow

Data Reference Chains

Data references can form chains:

Data flow:

  1. vpc outputs vpc_id

  2. subnet_module receives vpc_id via Data.vpc.vpc_id

  3. subnet_blueprint exposes subnet_id via Data.subnet_module.subnet_id

  4. instance receives subnet_id via Data.subnet_blueprint.subnet_id

Parallel Execution Optimization

Maximizing Parallelism

Design blueprints to maximize parallel execution:

Avoid:

Execution: A → B → C (sequential)

Prefer:

Execution: A, B, C (all parallel if A has no dependents)

Dependency Minimization

Reduce cross-package dependencies:

Less efficient:

Both s3_logs and eks must wait for vpc.

More efficient:

s3_logs and eks can run in parallel if eks doesn't actually need log_bucket immediately.

Package related resources together to reduce dependencies:

Internal package dependencies don't block other stacks from executing in parallel.

Best Practices

Data Reference Design

DO:

  • Use Data references for runtime values only

  • Reference outputs that will definitely be available

  • Design packages with clear output contracts

  • Use descriptive output keys

DON'T:

  • Reference outputs from packages that may not execute

  • Create circular dependencies (A depends on B, B depends on A)

  • Use Data references for static configuration (use Props)

Dependency Management

DO:

  • Minimize cross-package dependencies

  • Design for parallel execution where possible

  • Use Props for configuration, Data for runtime values

  • Group related resources in packages

DON'T:

  • Create unnecessary dependencies

  • Design sequential execution when parallel would work

  • Mix Props and Data references unnecessarily

Expression Usage

DO:

  • Use expressions for dynamic value calculation

  • Combine Data references with strings and Props

  • Use conditional logic when appropriate

  • Keep expressions readable

DON'T:

  • Create complex nested expressions

  • Use expressions for simple value passing

  • Rely on side effects in expressions

Testing Parallel Execution

Test your blueprint's execution behavior:

See also

Last updated

Was this helpful?