VPC & networking
Most Alchemy apps on AWS never touch a VPC. Lambda functions serve public traffic from Function URLs, and bindings wire access to tables, buckets, and queues without a single subnet. Networking becomes your problem when you run an ECS Service or an EC2 Instance — both need a VPC, subnets, and security groups — or when you attach to anything that lives inside one.
Alchemy gives you two altitudes: the Network helper, which
builds the standard public/private layout in one call, and the
canonical primitives underneath it, for when you need
explicit control.
The Network helper
Section titled “The Network helper”Network creates a
production-shaped VPC from the low-level primitives — VPC,
internet gateway, one public and one private subnet per
Availability Zone (2 AZs by default), route tables, routes, and
associations — and returns every underlying resource so you can
keep composing with raw AWS.EC2.* APIs:
const network = yield* AWS.EC2.Network("AppNetwork", { cidrBlock: "10.42.0.0/16",});Subnet CIDRs are derived from the VPC block automatically, and
the outputs you’ll reach for most — vpcId, publicSubnetIds,
privateSubnetIds — sit right on the result.
Turn on NAT and gateway endpoints when private subnets need a path out:
const network = yield* AWS.EC2.Network("AppNetwork", { cidrBlock: "10.42.0.0/16", availabilityZones: 2, nat: "single", gatewayEndpoints: ["s3"],});
yield* AWS.ECS.Service("ApiService", { cluster, task: { taskDefinitionArn: apiTask.taskDefinitionArn, containerName: apiTask.containerName, port: apiTask.port, }, vpcId: network.vpcId, subnets: network.publicSubnetIds, assignPublicIp: true,});nat: "none"(default) keeps private subnets isolated;"single"shares one NAT gateway;"per-az"creates one per Availability Zone for AZ-fault isolation.gatewayEndpointsattaches free S3/DynamoDB gateway endpoints to the private route tables, so that traffic never crosses the NAT.
If Network’s layout fits, use it and stop reading. The rest of
this page is the same network built by hand.
Building it by hand
Section titled “Building it by hand”VPC and internet gateway
Section titled “VPC and internet gateway”A Vpc is a private IPv4 range; an
InternetGateway is its
door to the internet:
const vpc = yield* AWS.EC2.Vpc("AppVpc", { cidrBlock: "10.80.0.0/16", enableDnsSupport: true, enableDnsHostnames: true,});
const igw = yield* AWS.EC2.InternetGateway("AppIgw", { vpcId: vpc.vpcId,});The two DNS toggles let instances resolve names and receive public DNS hostnames — you’ll want both on for anything serving public traffic.
Subnets
Section titled “Subnets”Subnets carve the VPC block into
per-AZ ranges. mapPublicIpOnLaunch is what makes a subnet
“public” from the instance’s point of view:
const subnetA = yield* AWS.EC2.Subnet("PublicSubnetA", { vpcId: vpc.vpcId, cidrBlock: "10.80.1.0/24", availabilityZone: az1, mapPublicIpOnLaunch: true,});
const subnetB = yield* AWS.EC2.Subnet("PublicSubnetB", { vpcId: vpc.vpcId, cidrBlock: "10.80.2.0/24", availabilityZone: az2, mapPublicIpOnLaunch: true,});Two subnets in two AZs is the floor for anything fronted by a load balancer.
Routing
Section titled “Routing”A subnet is only public once its
RouteTable sends 0.0.0.0/0
to the internet gateway. Route adds
the rule;
RouteTableAssociation
attaches the table to each subnet:
const routeTable = yield* AWS.EC2.RouteTable("PublicRouteTable", { vpcId: vpc.vpcId,});
yield* AWS.EC2.Route("PublicInternetRoute", { routeTableId: routeTable.routeTableId, destinationCidrBlock: "0.0.0.0/0", gatewayId: igw.internetGatewayId,});
yield* AWS.EC2.RouteTableAssociation("PublicAssocA", { routeTableId: routeTable.routeTableId, subnetId: subnetA.subnetId,});yield* AWS.EC2.RouteTableAssociation("PublicAssocB", { routeTableId: routeTable.routeTableId, subnetId: subnetB.subnetId,});Security groups
Section titled “Security groups”A SecurityGroup is the
per-resource firewall — the thing you attach to service ENIs,
load balancers, and instances. Declare ingress and egress rules
inline:
const securityGroup = yield* AWS.EC2.SecurityGroup("AppSg", { vpcId: vpc.vpcId, description: "app traffic", ingress: [ { ipProtocol: "tcp", fromPort: 80, toPort: 80, cidrIpv4: "0.0.0.0/0", description: "HTTP ingress", }, ], egress: [ { ipProtocol: "-1", cidrIpv4: "0.0.0.0/0", description: "all outbound", }, ],});Rules can also be managed as standalone
SecurityGroupRule
resources when different parts of your stack contribute rules to
one group.
Private egress with NAT
Section titled “Private egress with NAT”Private subnets reach the internet through a
NatGateway living in a
public subnet, addressed by an EIP,
with the private route table pointing 0.0.0.0/0 at it:
const privateRouteTable = yield* AWS.EC2.RouteTable("PrivateRouteTable", { vpcId: vpc.vpcId,});
const eip = yield* AWS.EC2.EIP("NatEip", { domain: "vpc" });
const natGateway = yield* AWS.EC2.NatGateway("NatGateway", { subnetId: subnetA.subnetId, // a public subnet allocationId: eip.allocationId, connectivityType: "public",});
yield* AWS.EC2.Route("PrivateInternetRoute", { routeTableId: privateRouteTable.routeTableId, destinationCidrBlock: "0.0.0.0/0", natGatewayId: natGateway.natGatewayId,});This is exactly what Network’s nat: "single" option builds
("per-az" repeats it per Availability Zone).
Gateway endpoints
Section titled “Gateway endpoints”S3 and DynamoDB traffic from private subnets doesn’t need NAT at
all — a Gateway VpcEndpoint
routes it over AWS’s network for free:
yield* AWS.EC2.VpcEndpoint("S3Endpoint", { vpcId: vpc.vpcId, serviceName: "com.amazonaws.us-east-1.s3", // match your region vpcEndpointType: "Gateway", routeTableIds: [privateRouteTable.routeTableId],});Network’s gatewayEndpoints: ["s3", "dynamodb"] does the same
against its private route tables.
The full toolkit
Section titled “The full toolkit”| Resource | What it does |
|---|---|
Vpc | The private IPv4 network everything else lives in |
Subnet | A per-AZ slice of the VPC’s address range |
InternetGateway | Two-way internet access for public subnets |
EgressOnlyInternetGateway | Outbound-only IPv6 internet access |
NatGateway | Outbound internet for private subnets |
EIP | A static public IPv4 address |
RouteTable / Route / RouteTableAssociation | Where each subnet’s traffic goes |
SecurityGroup / SecurityGroupRule | Stateful per-resource firewall |
VpcEndpoint | Private connectivity to AWS services |
NetworkAcl / NetworkAclEntry / NetworkAclAssociation | Stateless subnet-level packet filtering |
Where next
Section titled “Where next”- ECS — run containers in the network you just built, with an Alchemy-managed public ALB.
- EC2 — launch instances into it, raw or hosting an Effect program.
Networkreference — every prop and everything the helper returns.