Skip to content

Practical example: Lifeline

The Lifeline example demonstrates a complete Day-0 to Day-N infrastructure lifecycle. It shows how different teams collaborate, how to use modular architecture patterns, and how apply modes support different workflows.

This example is included with formae and can be found in /opt/pel/formae/examples/lifeline/.

Prerequisites: Understand Fundamentals, Modular infrastructure, and Workflows before diving into this example.

What you'll learn

  • How to organize complex infrastructure into focused modules
  • When to use reconcile vs patch mode
  • How different teams can work on the same infrastructure
  • The Day-0 to Day-N progression pattern

The Lifeline progression

Project structure

Lifeline organizes infrastructure into focused modules, each with a specific responsibility:

lifeline/
├── basic_infrastructure.pkl      # Main entry point
├── cross_cutting_change.pkl      # Cross-cutting updates
├── micro_change.pkl              # Application-specific changes
├── network_resources.pkl         # NetworkResources class
├── security_group_resources.pkl  # SecurityGroupResources class
└── vars.pkl                      # Shared configuration

Key architectural patterns

Class-based resources

Modules use classes to encapsulate related infrastructure components:

// network_resources.pkl
class NetworkResources {
    name: String
    vpcLabel: String
    vpcCidr: String
    subnetCidr1: String
    subnetCidr2: String
    region: String

    hidden vpc: vpc.VPC = new {
        label = vpcLabel
        cidrBlock = vpcCidr
        enableDnsHostnames = true
        enableDnsSupport = true
        tags { new { key = "Name"; value = formae.value(name + "-vpc").setOnce } }
    }

    hidden subnet1: subnet.Subnet = new {
        label = "lifeline-public-subnet-1"
        vpcId = vpc.res.id
        cidrBlock = subnetCidr1
        availabilityZone = "\(region)a"
        mapPublicIpOnLaunch = true
        tags { new { key = "Name"; value = formae.value(name + "-public-subnet-1").setOnce } }
    }

    // More resources...

    hidden resources: Listing<formae.Resource> = new {
        vpc
        subnet1
        // All resources...
    }
}

Classes provide better encapsulation and type safety compared to functions.

Clean import strategy

The main forma imports modules and shared configuration:

// basic_infrastructure.pkl
amends "@formae/forma.pkl"
import "@formae/formae.pkl"
import "@aws/aws.pkl"
import "@formae/ext/random.pkl"

import "./vars.pkl"
import "./network_resources.pkl" as nw
import "./security_group_resources.pkl" as sg

Shared configuration

The vars.pkl file contains stack, target, and properties used across all formae:

// vars.pkl - Note the stack and target patterns
projectName = "lifeline"
stackName = "lifeline"
region = "us-east-1"

regionProp = new formae.Prop {
    flag = "region"
    default = region
}

stack: formae.Stack = new {
    label = stackName
    description = "Stack for the lifeline showcase"
}

target: formae.Target = new formae.Target {
    label = "aws-target"
    config = new aws.Config {
        region = module.regionProp.value
    }
}

vpcLabel = "lifeline-vpc"
s3BucketSuffix = "-unique-bucket-id"
crossCuttingTag = "cross-cutting-tag"
crossCuttingTagValue = "cross-cutting-tag-value"

The complete workflow journey

This example demonstrates how different teams work on the same infrastructure over time using different apply modes.

Day 0: Platform engineers deploy foundation

formae apply --mode reconcile --watch basic_infrastructure.pkl

Platform engineers use reconcile mode to deploy the complete networking foundation. This creates VPC, subnets, internet gateway, route tables, and security groups.

Day 10: Platform engineers make structural changes

formae apply --mode reconcile --watch basic_infrastructure.pkl  # Updated version

Using reconcile mode again ensures the infrastructure matches the updated code exactly.

Day 50: Developers add application resources

formae apply --mode patch --watch micro_change.pkl

Developers use patch mode to add application-specific resources (like S3 buckets) without affecting the foundation infrastructure. The blast radius is minimal - only creates or updates, never destroys. This can be triggered from a GitHub workflow.

Day 90: Security team applies compliance update

formae apply --mode patch --watch cross_cutting_change.pkl

The security team uses patch mode to add compliance tags across multiple resources. While the blast radius in terms of resources touched can be large, the scope of changes is minimal and focused.

Day 100: Clean up everything

formae destroy --watch --query "stack:lifeline"

Working with ephemeral infrastructure or need to start over? Destroy all resources in the stack with a single command.

Understanding the forma files

Let's look at what each forma file does and why specific modes are used.

Foundation infrastructure (reconcile mode)

The basic_infrastructure.pkl creates core networking resources using reconcile mode:

local network = new nw.NetworkResources {
    name = properties.name.value
    vpcLabel = properties.vpcLabel.value
    vpcCidr = properties.vpcCidr.value
    subnetCidr1 = properties.subnetCidr1.value
    subnetCidr2 = properties.subnetCidr2.value
    region = vars.region
}

local securityGroups = new sg.SecurityGroupResources {
    name = properties.name.value
    vpc = network.vpc
}

forma {
    vars.stack
    vars.target

    ...network.resources
    ...securityGroups.resources
}

Why reconcile mode? This is your infrastructure foundation. You want complete control - reconcile mode ensures the infrastructure matches your code exactly, removing anything not defined.

Micro changes (patch mode)

Applying micro_change.pkl adds application-specific resources:

forma {
    vars.stack
    vars.target

    new bucket.Bucket {
        label = "bucket-1"
        bucketName = properties.bucketName.value
        tags {
            new {
                key = "Name"
                value = formae.value(properties.bucketName.value).setOnce
            }
            new {
                key = "Project"
                value = vars.projectName
            }
        }
    }
}

Why patch mode here? You're adding resources without changing the foundation. Minimal blast radius, minimal risk, fast deployment.

Cross-cutting changes (patch mode)

Applying cross_cutting_change.pkl updates security across existing resources:

forma {
    vars.stack
    vars.target

    new internetgateway.InternetGateway {
        label = "lifeline-igw"
        tags {
            new {
                key = vars.crossCuttingTag
                value = vars.crossCuttingTagValue
            }
        }
    }

    new securitygroup.SecurityGroup {
        label = "lifeline-alb-sg"
        groupDescription = "Allow HTTP traffic to ALB"
        tags {
            new {
                key = vars.crossCuttingTag
                value = vars.crossCuttingTagValue
            }
        }
    }

    new securitygroup.SecurityGroup {
        label = "lifeline-task-sg"
        groupDescription = "Allow HTTP traffic from ALB"
        tags {
            new {
                key = vars.crossCuttingTag
                value = vars.crossCuttingTagValue
            }
        }
    }
}

Why patch mode here? You're changing multiple resources that affect the foundation. There is minimal risk despite a potentially large blast radius, and no need to see unnecessary details in order to make orthogonal changes.

Takeaway Insight: Each apply mode serves different team workflows and risk profiles.

Try it yourself

You can run this example on your own AWS account:

  1. Copy the example:

    cd ~/projects
    cp -R /opt/pel/formae/examples/lifeline ./
    cd lifeline

  2. Review the code: Examine the class-based architecture and see how classes encapsulate related resources.

  3. Test with eval:

    # See what will be created
    formae eval basic_infrastructure.pkl
    
    # Test with different property values
    formae eval --region us-west-2 basic_infrastructure.pkl

  4. Deploy the foundation:

    formae apply --mode reconcile --watch basic_infrastructure.pkl

  5. Add application resources:

    formae apply --mode patch --watch micro_change.pkl

  6. Clean up when done:

    formae destroy --watch --query "stack:lifeline"

What's next

You've seen how to organize complex infrastructure using modules and apply modes. Continue learning: