This page requires JavaScript to display.
C
Unpacking...
← Cloud Platforms
Cloud Platforms

AWS CloudFormation for Data Engineers

Templates, stacks and change sets, a full data-lake stack, intrinsic functions and dynamic references, safe deployments, CDK and SAM, and how they compare with Terraform.

Contents
1. CloudFormation Concepts 2. Example: A Data Lake Stack 3. Intrinsic Functions & Dynamic References 4. Deploying & Reviewing Changes 5. AWS CDK & SAM 6. Common Interview Questions

1. CloudFormation Concepts

AWS CloudFormation provisions AWS resources from templates (YAML or JSON). A deployed template is a stack; CloudFormation works out the order of creation, rolls back on failure, and tracks what it manages, so environments are reproducible and changes are reviewed as code.

ConceptMeaning
TemplateDeclares Parameters, Mappings, Conditions, Resources (required) and Outputs
StackOne deployed instance of a template (e.g. data-lake-dev, data-lake-prod)
Change setA preview of what an update will add, modify or replace, before executing it
Drift detectionFinds resources changed outside CloudFormation (e.g. by hand in the console)
Nested stacksReusable templates referenced from a parent stack
StackSetsDeploy the same stack to many accounts and regions
Exports / ImportValueShare outputs (e.g. a bucket name) between stacks

2. Example: A Data Lake Stack

AWSTemplateFormatVersion: "2010-09-09"
Description: Data lake bucket, Glue database and ETL job

Parameters:
  Env:
    Type: String
    AllowedValues: [dev, test, prod]
  ScriptBucket:
    Type: String

Conditions:
  IsProd: !Equals [!Ref Env, prod]

Resources:
  LakeKey:
    Type: AWS::KMS::Key
    Properties:
      EnableKeyRotation: true
      KeyPolicy:
        Version: "2012-10-17"
        Statement:
          - Sid: AllowAccountAdmin
            Effect: Allow
            Principal: { AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root" }
            Action: "kms:*"
            Resource: "*"

  LakeBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain  # never delete data with the stack
    UpdateReplacePolicy: Retain
    Properties:
      BucketName: !Sub "acme-lake-${Env}-${AWS::AccountId}"
      VersioningConfiguration: { Status: Enabled }
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: aws:kms
              KMSMasterKeyID: !GetAtt LakeKey.Arn
            BucketKeyEnabled: true
      LifecycleConfiguration:
        Rules:
          - Id: raw-to-ia
            Status: Enabled
            Prefix: raw/
            Transitions:
              - { StorageClass: STANDARD_IA, TransitionInDays: 30 }

  SilverDatabase:
    Type: AWS::Glue::Database
    Properties:
      CatalogId: !Ref AWS::AccountId
      DatabaseInput: { Name: !Sub "silver_${Env}" }

  GlueRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal: { Service: glue.amazonaws.com }
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole
      Policies:
        - PolicyName: lake-access
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: [s3:GetObject, s3:PutObject, s3:DeleteObject]
                Resource: !Sub "${LakeBucket.Arn}/*"
              - Effect: Allow
                Action: s3:ListBucket
                Resource: !GetAtt LakeBucket.Arn

  RawToSilverJob:
    Type: AWS::Glue::Job
    Properties:
      Name: !Sub "raw-to-silver-${Env}"
      Role: !GetAtt GlueRole.Arn
      GlueVersion: "5.0"
      WorkerType: G.1X
      NumberOfWorkers: !If [IsProd, 20, 4]
      Command:
        Name: glueetl
        PythonVersion: "3"
        ScriptLocation: !Sub "s3://${ScriptBucket}/glue/raw_to_silver.py"
      DefaultArguments:
        "--job-bookmark-option": job-bookmark-enable
        "--enable-metrics": "true"

Outputs:
  LakeBucketName:
    Value: !Ref LakeBucket
    Export: { Name: !Sub "${AWS::StackName}-LakeBucket" }

3. Intrinsic Functions & Dynamic References

FunctionExampleReturns
!Ref!Ref LakeBucketA parameter value, or a resource's main identifier (bucket name, role name…)
!GetAtt!GetAtt GlueRole.ArnA specific attribute of a resource
!Sub!Sub "arn:aws:s3:::${LakeBucket}/*"A string with variables substituted
!Join / !Split!Join [",", [a, b]]Build or split strings
!If + Conditions!If [IsProd, 20, 4]Environment-specific values
!FindInMap!FindInMap [EnvConfig, !Ref Env, Workers]Lookup in a Mappings table
!ImportValue!ImportValue network-PrivateSubnetAAn output exported by another stack
# dynamic references resolve secrets and parameters at deploy time (never hard-code them)
MasterUserPassword: "{{resolve:secretsmanager:prod/orders-db:SecretString:password}}"
ImageTag: "{{resolve:ssm:/data-platform/etl-image-tag}}"

4. Deploying & Reviewing Changes

cfn-lint data-lake.yaml  # lint before anything else
aws cloudformation validate-template --template-body file://data-lake.yaml

aws cloudformation deploy \
  --template-file data-lake.yaml \
  --stack-name data-lake-prod \
  --parameter-overrides Env=prod ScriptBucket=acme-code-prod \
  --capabilities CAPABILITY_NAMED_IAM \
  --tags owner=data-platform costcentre=fraud \
  --no-execute-changeset  # create a change set to review first

aws cloudformation describe-change-set --stack-name data-lake-prod --change-set-name <name>
aws cloudformation execute-change-set --stack-name data-lake-prod --change-set-name <name>

aws cloudformation describe-stack-events --stack-name data-lake-prod --max-items 20  # why did it fail?
aws cloudformation detect-stack-drift --stack-name data-lake-prod
ProtectionWhy
DeletionPolicy: Retain / SnapshotKeep buckets and databases (or take a final snapshot) if the stack or resource is deleted
UpdateReplacePolicySame protection when an update would replace the resource
Termination protectionBlocks accidental stack deletion
Stack policiesForbid updates to critical resources
Change sets in CI/CDShow "Replacement: True" before it happens: replacing a database or bucket can mean data loss

5. AWS CDK & SAM

The AWS CDK lets you define infrastructure in Python (or TypeScript, Java…) with loops, functions and sensible defaults; it synthesises CloudFormation templates.

# app.py: pip install aws-cdk-lib constructs ; deploy with: cdk deploy
from aws_cdk import App, Stack, RemovalPolicy, Duration
from aws_cdk import aws_s3 as s3, aws_lambda as _lambda, aws_s3_notifications as s3n
from constructs import Construct

class IngestStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        bucket = s3.Bucket(self, "Inbound",
            encryption=s3.BucketEncryption.KMS_MANAGED,
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
            enforce_ssl=True, versioned=True,
            removal_policy=RemovalPolicy.RETAIN)

        validator = _lambda.Function(self, "Validator",
            runtime=_lambda.Runtime.PYTHON_3_12,
            handler="handler.handler",
            code=_lambda.Code.from_asset("lambda/validator"),
            timeout=Duration.seconds(60))

        bucket.grant_read(validator)  # least-privilege policy generated for you
        bucket.add_event_notification(s3.EventType.OBJECT_CREATED, s3n.LambdaDestination(validator),
                                      s3.NotificationKeyFilter(prefix="incoming/", suffix=".csv"))

app = App()
IngestStack(app, "ingest-dev")
app.synth()

AWS SAM is a CloudFormation extension with short syntax for serverless resources (functions, APIs, event sources) and a CLI to build, test locally and deploy (sam build, sam local invoke, sam deploy --guided).

ToolStrengthsChoose when
CloudFormationNative, no extra tooling, stack rollback and drift detectionAWS-only, declarative templates, StackSets across accounts
AWS CDKReal programming language, reusable constructs, less boilerplateDevelopers who prefer code and abstractions
AWS SAMConcise serverless syntax, local testingLambda-centric applications
TerraformMulti-cloud, large provider ecosystem, plan/apply workflowMulti-cloud or Databricks/SaaS resources alongside AWS

6. Common Interview Questions

QuestionShort answer
What is a change set?A preview of the adds, modifications and replacements an update will make, reviewed before executing
How do you protect a data bucket from stack deletion?DeletionPolicy: Retain and UpdateReplacePolicy: Retain, plus termination protection and stack policies
!Ref vs !GetAtt?!Ref returns a parameter value or the resource's primary identifier; !GetAtt returns a named attribute such as an ARN
How do you pass secrets to resources?Dynamic references to Secrets Manager or SSM Parameter Store, resolved at deploy time; never plain text parameters
What is drift?Differences between the template and real resources caused by manual changes; detect and reconcile them
CloudFormation vs CDK vs Terraform?CloudFormation: native declarative AWS. CDK: code that generates CloudFormation. Terraform: multi-cloud declarative tool with its own state