Constructs

Reusable constructs provided by the AWS CDK Starter Kit including BaseConstruct and NetworkConstruct.


Overview

The starter kit includes two constructs that handle environment-aware naming and common infrastructure patterns. Extend these for consistent behavior across your stacks.

Learn the fundamentals of creating AWS CDK constructs before diving into the patterns below.

BaseConstruct

Source: src/constructs/base-construct.ts

Base class that exposes environment context and safe naming helpers. All custom constructs should extend this class.

Constructor

new BaseConstruct(scope: Construct, id: string)
ParameterTypeDescription
scopeConstructParent construct scope
idstringUnique identifier within scope

Properties

PropertyTypeDescription
branchstring | undefinedCleaned branch name from GIT_BRANCH_REF. Returns undefined for main, develop, and version tags.
environmentstringEnvironment name from ENVIRONMENT variable. Defaults to dev.
accountstringAWS account ID of the current stack
regionstringAWS region of the current stack

Methods

unique

Generates environment or branch-suffixed resource names (max 64 characters).

unique(name: string): string
ParameterTypeDescription
namestringBase name for the resource

Returns: Suffixed resource name like data-123456789012-test or data-123456789012-feature-auth.

Usage example

import { Construct } from 'constructs';
import { BaseConstruct } from '../constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

export class DataBucketConstruct extends BaseConstruct {
  public readonly bucket: s3.Bucket;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    // Environment-aware bucket name
    this.bucket = new s3.Bucket(this, 'Bucket', {
      bucketName: this.unique(`data-${this.account}`),
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
    });

    // Conditional logic based on environment
    if (this.environment === 'production') {
      this.bucket.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN);
    }
  }
}

NetworkConstruct

Source: src/constructs/network-construct.ts

Creates an opinionated VPC with environment-specific configuration. Includes public, private, and isolated subnets plus gateway endpoints and flow logs.

Constructor

new NetworkConstruct(scope: Construct, id: string)
ParameterTypeDescription
scopeConstructParent construct scope
idstringUnique identifier within scope

Configuration by environment

SettingDevelopment/TestProduction
CIDR172.16.0.0/16 (dev), 172.17.0.0/16 (test)172.18.0.0/16
NAT Gateways13
Availability Zones33
Subnet size/20 per subnet/20 per subnet

Resources created

ResourceDescription
VPCThree-tier VPC with public, private, and isolated subnets
NAT GatewaysEnvironment-specific count for private subnet egress
Gateway EndpointsS3 and DynamoDB endpoints included
Flow LogsStored in encrypted S3 bucket with blocked public access

Properties

PropertyTypeDescription
vpcec2.VpcThe created VPC instance

Usage example

import { NetworkConstruct } from '../constructs';

export class AppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const network = new NetworkConstruct(this, 'Network');

    // Use the VPC for other resources
    new ecs.Cluster(this, 'Cluster', {
      vpc: network.vpc,
    });
  }
}

Creating custom constructs

Follow this pattern when building your own constructs:

// src/constructs/my-construct.ts
import { Construct } from 'constructs';
import { BaseConstruct } from './base-construct';

export interface MyConstructProps {
  readonly featureEnabled?: boolean;
}

export class MyConstruct extends BaseConstruct {
  constructor(scope: Construct, id: string, props?: MyConstructProps) {
    super(scope, id);

    // Access inherited properties
    console.log(`Environment: ${this.environment}`);
    console.log(`Branch: ${this.branch ?? 'none'}`);

    // Use unique() for resource names
    const resourceName = this.unique('my-resource');
  }
}

Export from index:

// src/constructs/index.ts
export { BaseConstruct } from './base-construct';
export { NetworkConstruct } from './network-construct';
export { MyConstruct } from './my-construct';

Next steps

  • Aspects - Add governance rules to your constructs
  • Stacks - See how constructs are used in stacks
  • Usage Examples - Common patterns and recipes