Skip to content

CDK Infrastructure

Prerequisites:

  • npm install @jaypie/constructs aws-cdk-lib constructs
  • AWS CDK CLI installed (npm install -g aws-cdk)
  • AWS credentials configured

Jaypie provides CDK constructs that automatically configure Datadog integration, environment variables, and IAM permissions. All Jaypie CDK applications extend JaypieStack classes for consistent configuration.

packages/cdk/
├── bin/
│ └── cdk.ts # CDK app entry point
├── lib/
│ ├── cdk-app.ts # Application stack
│ └── cdk-infra.ts # Infrastructure stack
├── cdk.json
├── package.json
└── tsconfig.json
Stack Extends Purpose
JaypieStack Stack (CDK) Base class — auto-naming, account/region resolution, standard tag set
JaypieAppStack JaypieStack Application resources (Lambda, API Gateway); pre-fills key: "app"
JaypieInfrastructureStack JaypieStack Shared infrastructure (VPC, databases); pre-fills key: "infra"

packages/cdk/bin/cdk.ts:

#!/usr/bin/env node
import * as cdk from "aws-cdk-lib";
import { AppStack } from "../lib/cdk-app.js";
import { InfraStack } from "../lib/cdk-infra.js";
const app = new cdk.App();
new InfraStack(app, "MyProject-Infra");
new AppStack(app, "MyProject-App");

packages/cdk/lib/cdk-app.ts:

import { JaypieAppStack, JaypieLambda, JaypieApiGateway } from "@jaypie/constructs";
import type { Construct } from "constructs";
export class AppStack extends JaypieAppStack {
constructor(scope: Construct, id: string) {
super(scope, id);
const api = new JaypieLambda(this, "Api", {
code: "../../api/dist",
handler: "handler.handler",
secrets: ["MONGODB_URI"],
});
new JaypieApiGateway(this, "Gateway", {
handler: api,
host: "api.example.com",
zone: "example.com",
});
}
}

packages/cdk/lib/cdk-infra.ts:

import { JaypieInfrastructureStack, JaypieEnvSecret } from "@jaypie/constructs";
import type { Construct } from "constructs";
export class InfraStack extends JaypieInfrastructureStack {
constructor(scope: Construct, id: string) {
super(scope, id);
new JaypieEnvSecret(this, "MongoSecret", {
secretName: "prod/mongodb-uri",
envName: "MONGODB_URI",
});
}
}

Standard Lambda function with Datadog layers and environment injection.

new JaypieLambda(this, "Worker", {
code: "../worker/dist",
handler: "index.handler",
secrets: ["API_KEY"],
timeout: cdk.Duration.seconds(30),
memorySize: 256,
environment: {
CUSTOM_VAR: "value",
},
});

Options:

Option Type Default Description
code string - Path to Lambda code directory
handler string - Handler function (file.function)
secrets JaypieEnvSecret[] - Secrets to inject
timeout Duration 30s Function timeout
memorySize number 128 Memory in MB
environment object - Additional env vars

Lambda triggered by SQS queue.

new JaypieQueuedLambda(this, "QueueWorker", {
code: "../worker/dist",
handler: "index.handler",
queueName: "tasks",
});
// Sets CDK_ENV_QUEUE_URL automatically

Lambda triggered by S3 events via SQS.

new JaypieBucketQueuedLambda(this, "FileProcessor", {
code: "../processor/dist",
handler: "index.handler",
bucketName: "uploads",
events: ["s3:ObjectCreated:*"],
});
// Sets CDK_ENV_BUCKET automatically

Express application on Lambda.

new JaypieExpressLambda(this, "Api", {
code: "../api/dist",
handler: "handler.handler",
});

REST API Gateway with custom domain.

new JaypieApiGateway(this, "Gateway", {
handler: lambdaFunction,
host: "api.example.com",
zone: "example.com",
});

Static site hosting on S3 with CloudFront, ACM, Route53, and (when CDK_ENV_REPO is set) a GitHub OIDC deploy role. Ships with security headers, WAFv2, and CloudFront access logging by default — same override mechanisms as JaypieDistribution.

new JaypieWebDeploymentBucket(this, "Web", {
host: "app.example.com",
zone: "example.com",
});
// HostConfig — resolved via envHostname()
new JaypieWebDeploymentBucket(this, "Web", {
host: { subdomain: "app", domain: "example.com" },
zone: "example.com",
});

DynamoDB table with Jaypie single-table design patterns.

import { fabricIndex } from "@jaypie/fabric";
// Basic table (no GSIs by default)
new JaypieDynamoDb(this, "myApp");
// With indexes using fabricIndex() from @jaypie/fabric
new JaypieDynamoDb(this, "myApp", {
indexes: [
fabricIndex(), // indexModel: pk=["model"], sk=["scope","updatedAt"]
fabricIndex("alias"), // indexModelAlias (sparse)
fabricIndex("category"), // indexModelCategory (sparse)
],
});

Secret reference for Lambda injection.

const secret = new JaypieEnvSecret(this, "ApiKey", {
secretName: "prod/api-key",
envName: "API_KEY",
});
new JaypieLambda(this, "Function", {
secrets: [secret],
});
// Lambda has SECRET_API_KEY pointing to Secrets Manager

packages/cdk/cdk.json:

{
"app": "npx tsx bin/cdk.ts",
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:stackRelativeExports": true
}
}

packages/cdk/package.json:

{
"name": "@project/cdk",
"version": "0.0.1",
"type": "module",
"private": true,
"scripts": {
"build": "tsc",
"cdk": "cdk",
"synth": "cdk synth",
"deploy": "cdk deploy"
}
}
Terminal window
# Synthesize CloudFormation
npm run synth -w packages/cdk
# Deploy to AWS
npm run deploy -w packages/cdk
# Deploy specific stack
cdk deploy MyProject-App -w packages/cdk
const env = process.env.PROJECT_ENV || "sandbox";
new AppStack(app, `MyProject-${env}`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});

Stack names must match GitHub Actions workflow configuration:

.github/workflows/deploy.yml
- name: Deploy
run: cdk deploy MyProject-App
// Must match exactly
new AppStack(app, "MyProject-App");