Skip to main content

AWS CDK

Infrastructure as Code with Java, Organized as Business Components

Overview

This architectural style applies the BCE pattern to AWS CDK v2 infrastructure written in Java: infrastructure is built the same way a business application is built: as business components, not as a flat pile of resources. A construct is a reusable capability; a stack is a deployment boundary. Keeping that split makes the infrastructure code readable, testable, and refactorable.

The result is a Maven, Java 25 CDK project whose packages are BCE business components. The entry-point class (CDKApp) loads typed configuration, wires stacks in dependency order, and calls app.synth(). Synthesis stays deterministic and side-effect free: no AWS SDK calls, no randomness, no timestamps during construction.

Business Components

Business components are packages named after the AWS capability they provision: s3, cloudfront, certificate, route53, dynamodb, lambda, cognito, codebuild, iam, stepfunctions. When a component spans multiple services, it is named after its domain responsibility instead of any single service.

The package path follows the familiar shape [organization].[application].[businessComponent].[boundary|control|entity]. A component uses only the layers it needs: a stateless resource factory is a control-only component (e.g. s3.control.Buckets); stacks from other components call it directly. Explicit IAM roles and policy statements live in a dedicated iam component, and Cognito always gets its own stack.

Boundary

Stacks are the boundaries. A stack class (extends Stack) is the CloudFormation deployment boundary: it composes constructs, connects cross-stack dependencies, applies tags, and declares outputs.

Control

Controls are reusable, stateless resource factories (bucket factories, a CodeBuild publishing project) and helpers that connect existing resources: Route53 alias records pointing at a CloudFront distribution, IAM grants, event subscriptions. They serve the same purpose as CDK constructs (reusable capabilities) without necessarily subclassing Construct. Prefer Java interfaces with static factory methods over utility classes.

Entity

Entities are immutable data describing infrastructure without creating resources: build specs, typed value objects, and configuration records. Configuration is parsed once at the application entry point and passed down as typed records; a stack never reaches back to the raw property source.

Principles

Stacks vs. Constructs

A stack is a deployment boundary; a construct is a reusable capability. Keeping the split makes infrastructure readable, testable, and refactorable.

Deterministic Synthesis

No AWS SDK calls, no randomness, no timestamps during construction. The same source and context always synthesize an equivalent template.

Least-Privilege IAM

grant* methods generate correctly-scoped policies. Explicit policy statements are the fallback, kept in a dedicated iam component.

Generated Names

CloudFormation generates physical names: bucket, table, and role names are omitted unless an operator-facing name is genuinely required.

Testing

Build & Deployment

Resources

Tools & References