FsCDK lets you describe AWS infrastructure with a small, expressive F# DSL built on top of the AWS Cloud Development Kit (CDK). If you like computation expressions, immutability, and readable diffs, you’ll feel right at home.
This page gives you a quick, human-sized tour. No buzzwords, just a couple of realistic stacks you can read end-to-end.
What you’ll see below: - Define per-environment settings once and reuse them. - Declare DynamoDB tables, Lambdas, queues and topics with intent, not boilerplate. - Wire resources together (grants and subscriptions) without hunting for ARNs.
#r "../src/bin/Release/net8.0/publish/Amazon.JSII.Runtime.dll"
#r "../src/bin/Release/net8.0/publish/Constructs.dll"
#r "../src/bin/Release/net8.0/publish/Amazon.CDK.Lib.dll"
#r "../src/bin/Release/net8.0/publish/System.Text.Json.dll"
#r "../src/bin/Release/net8.0/publish/FsCDK.dll"
open FsCDK
open Amazon.CDK
open Amazon.CDK.AWS.DynamoDB
open Amazon.CDK.AWS.Lambda
// 1) Environments
let devEnv =
environment {
account "123456789012"
region "us-east-1"
}
let prodEnv =
environment {
account "123456789012"
region "us-east-1"
}
// 2) A Dev stack you can actually work with
stack "Dev" {
env devEnv
description "Developer stack for feature work"
tags [ "service", "users"; "env", "dev" ]
// resources
table "users" {
partitionKey "id" AttributeType.STRING
billingMode BillingMode.PAY_PER_REQUEST
removalPolicy RemovalPolicy.DESTROY
}
lambda "users-api-dev" {
handler "Users::Handler::FunctionHandler"
runtime Runtime.DOTNET_8
code "./examples/lambdas/users"
memorySize 512
timeout 10.0
description "CRUD over the users table"
}
let! usersDlq =
queue "users-dlq" {
retentionPeriod (7.0 * 24.0 * 3600.0) // 7 days
}
let dlq =
deadLetterQueue {
queue usersDlq
maxReceiveCount 5
}
queue "users-queue" {
deadLetterQueue dlq
visibilityTimeout 30.0
}
topic "user-events" { displayName "User events" }
grant {
table "users"
lambda "users-api-dev"
readWriteAccess
}
}
stack "Prod" {
env prodEnv
terminationProtection true
tags [ "service", "users"; "env", "prod" ]
table "users" {
partitionKey "id" AttributeType.STRING
billingMode BillingMode.PAY_PER_REQUEST
removalPolicy RemovalPolicy.RETAIN
pointInTimeRecovery true
}
lambda "users-api" {
handler "Users::Handler::FunctionHandler"
runtime Runtime.DOTNET_8
code "./examples/lambdas/users"
memorySize 1024
timeout 15.0
description "CRUD over the users table"
}
grant {
table "users"
lambda "users-api"
readWriteAccess
}
}
Why FsCDK?

FsCDK Architecture Overview
Production-Safe Defaults
- Implements Yan Cui's serverless best practices by default
- Auto-creates Dead Letter Queues (DLQs) for Lambda functions
- Enables X-Ray tracing and structured JSON logging
- Sets conservative concurrency limits to prevent runaway costs
Security by Default
- S3 buckets block public access and enforce SSL/TLS
- Lambda environment variables encrypted with KMS
- Security groups deny all outbound traffic by default (opt-in model)
F# Developer Experience
- Type-safe computation expressions for all AWS resources
- Immutable configuration with compile-time checks
- IntelliSense support for discovering available options
- Readable diffs in version control
List of builders and their operations
(Most of them, this might not be complete)
AWS Resource |
Builder Name(s) |
Parameters |
|---|---|---|
ALB |
|
|
App Runner Service |
|
|
AppSync GraphQL API |
|
|
Bastion Host |
|
|
Bucket |
|
|
CDK App |
|
|
CloudWatch Alarm |
|
|
CloudWatch Log Group |
|
|
CloudWatch Metric Filter |
|
|
CloudWatch Subscription Filter |
|
|
CloudHSM Cluster |
|
|
CloudTrail |
|
|
Cors Rule |
|
|
Custom Resource |
|
|
Database Instance |
|
|
Distribution |
|
|
DocumentDB Cluster |
|
|
ECR Lifecycle Rule |
(helpers) |
|
ECR Repository |
|
|
ECS Cluster |
|
|
ECS Fargate Service |
|
|
EKS Cluster |
|
|
ElastiCache Redis |
|
|
Elastic Beanstalk Application |
|
|
Elastic Beanstalk Environment |
|
|
Event BridgeRule |
|
|
Event Bus |
|
|
Fargate Task Definition |
|
|
Function |
|
|
Gateway VPC Endpoint |
|
|
Grant |
|
|
HTTP API (API Gateway V2) |
|
|
IAM PolicyStatement |
|
(none - uses method chaining, not CustomOperations) |
Import Source |
|
|
Interface VPC Endpoint |
|
|
Kinesis Stream |
|
|
KMS Key |
|
|
LambdaRole |
|
|
Origin Access Identity |
|
|
Queue |
|
|
RDS Proxy |
|
|
REST API (API Gateway V1) |
|
|
Route53 ARecord |
|
|
Route53 HostedZone |
|
|
Route53 PrivateHostedZone |
|
|
Route Table |
|
|
Route |
|
|
Secrets Manager Secret |
|
|
Security Group |
|
|
SSM Parameter |
|
|
SSM Document |
|
|
Stack |
|
- |
Step Functions |
|
|
Subscription |
|
|
Table |
|
|
Token Authorizer |
|
|
Topic |
|
|
User Pool |
|
|
User Pool Client |
|
|
Vpc |
|
|
VPC Link |
|
|
X-Ray Group |
|
|
X-Ray Sampling Rule |
|
|
The following AWS services are supported by FsCDK
Service |
What it does |
|
|---|---|---|
Distributes incoming HTTP/HTTPS traffic across multiple targets 📚 with curated learning resources |
||
Creates REST and HTTP APIs to expose your backend services 📚 with curated learning resources |
||
|
App Runner |
Fully managed container service for web apps and APIs |
|
AppSync |
Builds managed GraphQL APIs with real-time data synchronization |
Secure SSH access to instances in private subnets 📚 with curated learning resources |
||
Manages SSL/TLS certificates for secure connections 📚 with curated learning resources |
||
|
CloudFront |
Content delivery network (CDN) for fast global content distribution |
|
CloudHSM |
Hardware security modules for cryptographic key storage |
Monitors resources with alarms, log groups, metric filters, subscription filters, dashboards, and synthetic canaries |
||
|
Cognito |
User authentication and authorization for web and mobile apps |
|
DocumentDB |
MongoDB-compatible document database |
Fully managed NoSQL database for key-value and document data |
||
Virtual servers in the cloud |
||
Stores and manages Docker container images |
||
Runs containerized applications using Docker and Fargate |
||
|
EFS (Elastic File System) |
Scalable file storage for Lambda and EC2 |
Managed Kubernetes clusters for container orchestration |
||
|
ElastiCache |
In-memory caching with Redis and Memcached |
|
Elastic Beanstalk |
Platform-as-a-Service (PaaS) for deploying applications |
|
Elastic IP |
Static IPv4 addresses for dynamic cloud computing |
Event bus for connecting applications with event-driven architecture |
||
Controls access to AWS resources with users, roles, and policies |
||
Real-time data streaming for analytics and processing |
||
Creates and manages encryption keys |
||
Runs code without managing servers (serverless functions) with cost optimization controls |
||
High-performance TCP/UDP load balancer |
||
|
OIDC Provider |
Federated identity using OpenID Connect |
Managed relational databases (PostgreSQL, MySQL, etc.) |
||
|
Route53 |
DNS service and domain name management |
Object storage for files, backups, and static websites |
||
Securely stores and rotates database credentials and API keys |
||
Pub/sub messaging for sending notifications |
||
Message queuing for decoupling and scaling applications |
||
|
SSM (Systems Manager) |
Manages parameters and documents for configuration |
Coordinates multiple AWS services into serverless workflows |
||
|
VPC (Virtual Private Cloud) |
Isolated network environment for your AWS resources |
|
X-Ray |
Distributed tracing for debugging and analyzing microservices |
Additional Capabilities
- Custom Resources - Define custom CloudFormation resources
- Lambda Powertools - Production-ready observability for Lambda functions
- Grants - Simplified IAM permission management between resources
- Tags - Resource tagging across stacks
- Production-Safe Defaults - Security and reliability best practices built-in
<summary>Creates an AWS CDK Environment configuration.</summary>
<code lang="fsharp"> environment { account "123456789012" region "us-west-2" } </code>
<summary>Sets the AWS account ID for the environment.</summary>
<param name="config">The current configuration.</param>
<param name="accountId">The AWS account ID.</param>
<code lang="fsharp"> environment { account "123456789012" } </code>
<summary>Sets the AWS region for the environment.</summary>
<param name="config">The current configuration.</param>
<param name="regionName">The AWS region name.</param>
<code lang="fsharp"> environment { region "us-west-2" } </code>
<summary>Creates an AWS CDK Stack construct.</summary>
<param name="name">The name of the stack.</param>
<code lang="fsharp"> stack "MyStack" { lambda myFunction bucket myBucket } </code>
<summary>Sets the stack description.</summary>
<param name="config">The current stack configuration.</param>
<param name="desc">A description of the stack.</param>
<code lang="fsharp"> stack "MyStack" { description "My application stack" } </code>
<summary>Adds tags to the stack.</summary>
<param name="config">The current stack configuration.</param>
<param name="tags">A list of key-value pairs for tagging.</param>
<code lang="fsharp"> stack "MyStack" { tags [ "Environment", "Production"; "Team", "DevOps" ] } </code>
<summary>Creates a DynamoDB table configuration.</summary>
<param name="name">The table name.</param>
<code lang="fsharp"> table "MyTable" { partitionKey "id" AttributeType.STRING billingMode BillingMode.PAY_PER_REQUEST } </code>
<summary>Sets the partition key for the table.</summary>
<param name="config">The current table configuration.</param>
<param name="name">The attribute name for the partition key.</param>
<param name="attrType">The attribute type (STRING, NUMBER, or BINARY).</param>
<code lang="fsharp"> table "MyTable" { partitionKey "id" AttributeType.STRING } </code>
<summary>Sets the billing mode for the table.</summary>
<param name="config">The current table configuration.</param>
<param name="mode">The billing mode (PAY_PER_REQUEST or PROVISIONED).</param>
<code lang="fsharp"> table "MyTable" { billingMode BillingMode.PAY_PER_REQUEST } </code>
<summary>Sets the removal policy for the table.</summary>
<param name="config">The current table configuration.</param>
<param name="policy">The removal policy (DESTROY, RETAIN, or SNAPSHOT).</param>
<code lang="fsharp"> table "MyTable" { removalPolicy RemovalPolicy.DESTROY } </code>
<summary>Creates a Lambda function configuration.</summary>
<param name="name">The function name.</param>
<code lang="fsharp"> lambda "MyFunction" { handler "index.handler" runtime Runtime.NODEJS_18_X code "./lambda" timeout 30.0 } </code>
<summary>Sets the handler for the Lambda function.</summary>
<param name="config">The function configuration.</param>
<param name="handler">The handler name (e.g., "index.handler").</param>
<code lang="fsharp"> lambda "MyFunction" { handler "index.handler" } </code>
<summary>Sets the runtime for the Lambda function.</summary>
<param name="config">The function configuration.</param>
<param name="runtime">The Lambda runtime.</param>
<code lang="fsharp"> lambda "MyFunction" { runtime Runtime.NODEJS_18_X } </code>
type Runtime = inherit DeputyBase new: name: string * ?family: Nullable<RuntimeFamily> * ?props: ILambdaRuntimeProps -> unit member RuntimeEquals: other: Runtime -> bool member ToString: unit -> string member BundlingImage: DockerImage member Family: Nullable<RuntimeFamily> member IsVariable: bool member Name: string member SupportsCodeGuruProfiling: bool member SupportsInlineCode: bool ...
--------------------
Runtime(name: string, ?family: System.Nullable<RuntimeFamily>, ?props: ILambdaRuntimeProps) : Runtime
<summary>Sets the code source from a Code object.</summary>
<param name="config">The function configuration.</param>
<param name="path">The Code object.</param>
<code lang="fsharp"> lambda "MyFunction" { code (Code.FromBucket myBucket "lambda.zip") } </code>
<summary>Sets the memory allocation for the Lambda function.</summary>
<param name="config">The function configuration.</param>
<param name="mb">The memory size in megabytes.</param>
<code lang="fsharp"> lambda "MyFunction" { memory 512 } </code>
<summary>Sets the timeout for the Lambda function.</summary>
<param name="config">The function configuration.</param>
<param name="seconds">The timeout in seconds.</param>
<code lang="fsharp"> lambda "MyFunction" { timeout 30.0 } </code>
<summary>Sets the description for the Lambda function.</summary>
<param name="config">The function configuration.</param>
<param name="desc">The function description.</param>
<code lang="fsharp"> lambda "MyFunction" { description "Processes incoming orders" } </code>
<summary>Creates an SQS queue configuration.</summary>
<param name="name">The queue name.</param>
<code lang="fsharp"> queue "MyQueue" { visibilityTimeout 30.0 fifo true } </code>
<summary>Sets the message retention period for the queue.</summary>
<param name="config">The queue configuration.</param>
<param name="seconds">The retention period in seconds.</param>
<code lang="fsharp"> queue "MyQueue" { retentionPeriod 345600.0 // 4 days } </code>
<summary>Creates a dead-letter queue configuration.</summary>
<code lang="fsharp"> deadLetterQueue { queue myDeadLetterQueue maxReceiveCount 5 } </code>
<summary>Sets the queue that will receive dead letters.</summary>
<param name="config">The dead-letter queue configuration.</param>
<param name="queue">The queue to use as the dead-letter queue.</param>
<code lang="fsharp"> deadLetterQueue { queue myDeadLetterQueue maxReceiveCount 5 } </code>
<summary>Sets the maximum number of times a message can be delivered to the source queue before being moved to the dead-letter queue.</summary>
<param name="config">The dead-letter queue configuration.</param>
<param name="count">The maximum receive count.</param>
<code lang="fsharp"> deadLetterQueue { maxReceiveCount 10 } </code>
<summary>Configures a dead-letter queue for the queue.</summary>
<param name="config">The queue configuration.</param>
<param name="deadLetterQueue">The dead-letter queue configuration.</param>
<code lang="fsharp"> queue "MyQueue" { deadLetterQueue myDeadLetterQueue } </code>
<summary>Sets the visibility timeout for messages in the queue.</summary>
<param name="config">The queue configuration.</param>
<param name="seconds">The visibility timeout in seconds.</param>
<code lang="fsharp"> queue "MyQueue" { visibilityTimeout 30.0 } </code>
<summary>Creates an SNS topic configuration.</summary>
<param name="name">The topic name.</param>
<code lang="fsharp"> topic "MyTopic" { displayName "My Notification Topic" fifo true } </code>
<summary>Sets the display name for the topic.</summary>
<param name="displayName">The display name shown in email notifications.</param>
<code lang="fsharp"> topic "MyTopic" { displayName "Order Notifications" } </code>
<summary>Creates a grant configuration for permissions between resources.</summary>
<code lang="fsharp"> grant { table "MyTable" lambda "MyFunction" readWriteAccess } </code>
<summary>Sets the DynamoDB table for the grant.</summary>
<param name="tableConstructId">The construct ID of the table.</param>
<code lang="fsharp"> grant { table "MyTable" } </code>
<summary>Sets the Lambda function for the grant.</summary>
<param name="lambdaConstructId">The construct ID of the Lambda function.</param>
<code lang="fsharp"> grant { lambda "MyFunction" } </code>
<summary>Grants read and write access to the table.</summary>
<code lang="fsharp"> grant { table "MyTable" lambda "MyFunction" readWriteAccess } </code>
<summary>Enables or disables termination protection for the stack.</summary>
<param name="config">The current stack configuration.</param>
<param name="enabled">Whether termination protection is enabled.</param>
<code lang="fsharp"> stack "MyStack" { terminationProtection true } </code>
<summary>Enables or disables point-in-time recovery.</summary>
<param name="config">The current table configuration.</param>
<param name="enabled">Whether point-in-time recovery is enabled.</param>
<code lang="fsharp"> table "MyTable" { pointInTimeRecovery true } </code>
FsCDK