CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pulumi--aws

A Pulumi package for creating and managing Amazon Web Services (AWS) cloud resources with infrastructure-as-code.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

overview.mddocs/networking/

AWS Networking Services Overview

Guide to selecting and using AWS networking services with Pulumi.

Service Categories

Core Networking

Foundation of AWS networking - VPCs, subnets, routing

  • VPC - Virtual Private Cloud, isolated network environments
  • Subnets - Network segments within VPCs
  • Route Tables - Control traffic routing
  • Internet Gateway - VPC internet connectivity
  • NAT Gateway - Outbound internet for private subnets
  • VPC Peering - Connect VPCs privately
  • Transit Gateway - Hub for multi-VPC connectivity

Load Balancing

Distribute traffic across targets

  • ALB - Application Load Balancer (Layer 7, HTTP/HTTPS)
  • NLB - Network Load Balancer (Layer 4, TCP/UDP)
  • Gateway Load Balancer - Third-party appliances
  • Classic Load Balancer - Legacy (use ALB/NLB instead)

DNS & Domain Management

Name resolution and routing

  • Route 53 - DNS service, domain registration, health checks
  • Route 53 Resolver - Hybrid DNS between AWS and on-premises

Content Delivery

Global edge locations, low latency

  • CloudFront - Content Delivery Network (CDN)
  • Global Accelerator - Anycast static IP, improved availability

API Management

Build and manage APIs

  • API Gateway - REST APIs, WebSocket APIs
  • API Gateway v2 - HTTP APIs (cheaper, faster)
  • AppSync - GraphQL APIs

Connectivity

Hybrid and inter-region connections

  • Direct Connect - Dedicated network connection to AWS
  • VPN - Site-to-Site and Client VPN
  • PrivateLink - Private access to AWS services
  • VPC Endpoints - Private connections to AWS services

Security & Filtering

Network protection

  • Security Groups - Stateful instance-level firewall
  • Network ACLs - Stateless subnet-level firewall
  • Network Firewall - Advanced network protection
  • WAF - Web Application Firewall

Service Mesh & Discovery

Microservices networking

  • App Mesh - Service mesh for microservices
  • Cloud Map - Service discovery
  • VPC Lattice - Application networking

Decision Tree

Choose Your Networking Services

Start: What are you building?

┌─ Basic web application
│  ├─ VPC with public/private subnets
│  ├─ Internet Gateway for public access
│  ├─ NAT Gateway for private subnet outbound
│  ├─ ALB for load balancing
│  └─ Security Groups for instance protection
│
┌─ Multi-tier application
│  ├─ VPC with 3-tier architecture
│  │  ├─ Public subnet → ALB
│  │  ├─ Private subnet → Application servers
│  │  └─ Private subnet → Databases
│  ├─ NAT Gateway for app servers
│  ├─ Internal ALB for app tier
│  └─ Security Groups per tier
│
┌─ Global application
│  ├─ Multi-region deployment
│  ├─ Route 53 for DNS routing
│  │  ├─ Latency-based routing
│  │  ├─ Geolocation routing
│  │  └─ Failover routing
│  ├─ CloudFront for static content
│  └─ Global Accelerator for dynamic content
│
┌─ API backend
│  ├─ REST API → API Gateway (REST) + Lambda
│  ├─ HTTP API → API Gateway v2 (HTTP) + Lambda (cheaper)
│  ├─ WebSocket → API Gateway v2 (WebSocket)
│  └─ GraphQL → AppSync
│
┌─ Hybrid connectivity
│  ├─ Consistent high bandwidth → Direct Connect
│  ├─ Encrypted connectivity → Site-to-Site VPN
│  ├─ Remote access → Client VPN
│  └─ Multiple VPCs → Transit Gateway
│
└─ Microservices
   ├─ Service mesh → App Mesh
   ├─ Service discovery → Cloud Map
   ├─ Modern application networking → VPC Lattice
   └─ Container networking → ECS with service discovery

Service Selection Guide

Use VPC When

  • Always - VPC is the foundation of AWS networking
  • Isolate resources logically
  • Define IP address ranges
  • Control routing and security
  • Connect to on-premises networks

VPC design best practices:

  • Use RFC 1918 private address ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • Plan CIDR blocks to avoid overlaps
  • Use /16 for VPC (65,536 IPs)
  • Use /24 for subnets (256 IPs)
  • Create subnets in multiple AZs for HA
  • Separate public and private subnets
  • Reserve IP space for future growth

Subnet strategy:

  • Public subnets - Route to Internet Gateway (web servers, load balancers)
  • Private subnets - No direct internet (application servers, databases)
  • Database subnets - Separate tier for databases (optional)

Use ALB When

  • HTTP/HTTPS traffic (Layer 7)
  • Need path-based or host-based routing
  • Microservices or containerized apps
  • Need WebSocket support
  • Require native authentication (Cognito, OIDC)
  • Want Lambda targets

ALB features:

  • Path-based routing (/api → backend, /images → S3)
  • Host-based routing (api.example.com, www.example.com)
  • Content-based routing (headers, query strings)
  • Sticky sessions (session affinity)
  • HTTP/2 and gRPC support
  • WebSocket support
  • AWS WAF integration

Use NLB When

  • TCP/UDP traffic (Layer 4)
  • Need ultra-high performance (millions of requests/sec)
  • Require static IP addresses
  • Need to preserve source IP
  • Non-HTTP protocols

NLB features:

  • Extreme performance (millions of requests/sec)
  • Static IP per AZ (can use Elastic IP)
  • Preserve source IP address
  • TLS termination support
  • UDP support
  • PrivateLink support

Use Route 53 When

  • Need DNS for your applications
  • Domain registration and management
  • Health checks and failover
  • Traffic routing policies
  • Global load balancing

Routing policies:

  • Simple - Single resource (A record)
  • Weighted - Distribute traffic by percentage
  • Latency - Route to lowest latency region
  • Failover - Primary/secondary with health checks
  • Geolocation - Route based on user location
  • Geoproximity - Route based on resource and user location
  • Multi-value - Multiple IPs with health checks

Use cases:

  • Domain management and DNS hosting
  • Multi-region failover
  • A/B testing (weighted routing)
  • Geo-targeting (geolocation routing)
  • Disaster recovery (failover routing)

Use CloudFront When

  • Serving static content globally (images, videos, downloads)
  • Improving website performance
  • Need edge locations close to users
  • Want to reduce origin load
  • Require DDoS protection (Shield Standard)

Origin options:

  • S3 bucket - Static website, media files
  • ALB/NLB - Dynamic content
  • EC2 instance - Custom origin
  • API Gateway - API caching
  • Custom origin - Any HTTP server

Cache behaviors:

  • Configure TTL per content type
  • Use origin request policies
  • Implement cache key customization
  • Set up signed URLs/cookies for private content

Use API Gateway When

REST API:

  • Full-featured API management
  • Need API keys, usage plans, throttling
  • Require resource policies
  • Want private APIs (VPC endpoints)
  • Need request/response transformations

HTTP API (v2):

  • Simple HTTP APIs
  • Lower latency (up to 60% cheaper)
  • JWT authorizers
  • CORS support
  • OIDC/OAuth 2.0 integration

WebSocket API:

  • Real-time bidirectional communication
  • Chat applications
  • Live dashboards
  • Gaming backends

When to use AppSync instead:

  • Need GraphQL API
  • Real-time subscriptions
  • Offline data sync
  • Multiple data sources

Use Direct Connect When

  • Consistent network performance required
  • Large data transfers to AWS (lower bandwidth costs)
  • Hybrid cloud architecture
  • Compliance requirements for private connectivity
  • Need predictable bandwidth (1 Gbps or 10 Gbps)

Direct Connect vs VPN:

  • Direct Connect: Dedicated, consistent, higher bandwidth, more expensive
  • VPN: Encrypted, internet-based, variable bandwidth, lower cost

Use both: Direct Connect for primary, VPN for backup

Use Transit Gateway When

  • Connecting multiple VPCs (more than 3)
  • Hub-and-spoke network topology
  • Centralized routing
  • Need VPN connections to multiple VPCs
  • Inter-region VPC connectivity

Transit Gateway benefits:

  • Simplifies network topology
  • Centralized routing tables
  • Supports thousands of VPCs
  • Inter-region peering
  • Multicast support

Transit Gateway vs VPC Peering:

  • Transit Gateway: Many VPCs, centralized, transitive routing
  • VPC Peering: Two VPCs, decentralized, no transitive routing

Common Patterns

Pattern 1: Three-Tier Web Application

VPC + ALB + Auto Scaling

import * as aws from "@pulumi/aws";

// VPC
const vpc = new aws.ec2.Vpc("main-vpc", {
    cidrBlock: "10.0.0.0/16",
    enableDnsHostnames: true,
    enableDnsSupport: true,
    tags: { Name: "main-vpc" },
});

// Public subnets (2 AZs)
const publicSubnet1 = new aws.ec2.Subnet("public-1", {
    vpcId: vpc.id,
    cidrBlock: "10.0.1.0/24",
    availabilityZone: "us-east-1a",
    mapPublicIpOnLaunch: true,
    tags: { Name: "public-subnet-1", Tier: "public" },
});

const publicSubnet2 = new aws.ec2.Subnet("public-2", {
    vpcId: vpc.id,
    cidrBlock: "10.0.2.0/24",
    availabilityZone: "us-east-1b",
    mapPublicIpOnLaunch: true,
    tags: { Name: "public-subnet-2", Tier: "public" },
});

// Private subnets for application tier
const appSubnet1 = new aws.ec2.Subnet("app-1", {
    vpcId: vpc.id,
    cidrBlock: "10.0.11.0/24",
    availabilityZone: "us-east-1a",
    tags: { Name: "app-subnet-1", Tier: "application" },
});

const appSubnet2 = new aws.ec2.Subnet("app-2", {
    vpcId: vpc.id,
    cidrBlock: "10.0.12.0/24",
    availabilityZone: "us-east-1b",
    tags: { Name: "app-subnet-2", Tier: "application" },
});

// Private subnets for database tier
const dbSubnet1 = new aws.ec2.Subnet("db-1", {
    vpcId: vpc.id,
    cidrBlock: "10.0.21.0/24",
    availabilityZone: "us-east-1a",
    tags: { Name: "db-subnet-1", Tier: "database" },
});

const dbSubnet2 = new aws.ec2.Subnet("db-2", {
    vpcId: vpc.id,
    cidrBlock: "10.0.22.0/24",
    availabilityZone: "us-east-1b",
    tags: { Name: "db-subnet-2", Tier: "database" },
});

// Internet Gateway
const igw = new aws.ec2.InternetGateway("igw", {
    vpcId: vpc.id,
    tags: { Name: "main-igw" },
});

// NAT Gateway (1 per AZ for HA)
const eip1 = new aws.ec2.Eip("nat-eip-1", { vpc: true });
const natGw1 = new aws.ec2.NatGateway("nat-1", {
    subnetId: publicSubnet1.id,
    allocationId: eip1.id,
    tags: { Name: "nat-gateway-1" },
});

// Route tables
const publicRt = new aws.ec2.RouteTable("public-rt", {
    vpcId: vpc.id,
    routes: [{ cidrBlock: "0.0.0.0/0", gatewayId: igw.id }],
    tags: { Name: "public-route-table" },
});

const privateRt = new aws.ec2.RouteTable("private-rt", {
    vpcId: vpc.id,
    routes: [{ cidrBlock: "0.0.0.0/0", natGatewayId: natGw1.id }],
    tags: { Name: "private-route-table" },
});

// Route table associations
const publicRta1 = new aws.ec2.RouteTableAssociation("public-rta-1", {
    subnetId: publicSubnet1.id,
    routeTableId: publicRt.id,
});

const appRta1 = new aws.ec2.RouteTableAssociation("app-rta-1", {
    subnetId: appSubnet1.id,
    routeTableId: privateRt.id,
});

// Application Load Balancer
const albSg = new aws.ec2.SecurityGroup("alb-sg", {
    vpcId: vpc.id,
    ingress: [
        { protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] },
        { protocol: "tcp", fromPort: 443, toPort: 443, cidrBlocks: ["0.0.0.0/0"] },
    ],
    egress: [{ protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: ["0.0.0.0/0"] }],
});

const alb = new aws.lb.LoadBalancer("app-alb", {
    loadBalancerType: "application",
    subnets: [publicSubnet1.id, publicSubnet2.id],
    securityGroups: [albSg.id],
    tags: { Name: "app-alb" },
});

const targetGroup = new aws.lb.TargetGroup("app-tg", {
    port: 80,
    protocol: "HTTP",
    vpcId: vpc.id,
    healthCheck: {
        path: "/health",
        interval: 30,
        timeout: 5,
        healthyThreshold: 2,
        unhealthyThreshold: 2,
    },
});

const listener = new aws.lb.Listener("app-listener", {
    loadBalancerArn: alb.arn,
    port: 80,
    protocol: "HTTP",
    defaultActions: [{
        type: "forward",
        targetGroupArn: targetGroup.arn,
    }],
});

export const albDns = alb.dnsName;

Use when: Traditional web applications, multi-tier architectures

Pattern 2: Serverless API

API Gateway + Lambda + DynamoDB

// Lambda function
const handler = new aws.lambda.Function("api", {
    runtime: "nodejs20.x",
    handler: "index.handler",
    role: lambdaRole.arn,
    code: new pulumi.asset.FileArchive("./app"),
    environment: {
        variables: { TABLE_NAME: table.name },
    },
});

// API Gateway HTTP API (v2)
const api = new aws.apigatewayv2.Api("http-api", {
    protocolType: "HTTP",
    corsConfiguration: {
        allowOrigins: ["*"],
        allowMethods: ["GET", "POST", "PUT", "DELETE"],
        allowHeaders: ["content-type", "authorization"],
    },
});

// Lambda integration
const integration = new aws.apigatewayv2.Integration("lambda-integration", {
    apiId: api.id,
    integrationType: "AWS_PROXY",
    integrationUri: handler.arn,
    payloadFormatVersion: "2.0",
});

// Routes
const getRoute = new aws.apigatewayv2.Route("get-route", {
    apiId: api.id,
    routeKey: "GET /users",
    target: pulumi.interpolate`integrations/${integration.id}`,
});

const postRoute = new aws.apigatewayv2.Route("post-route", {
    apiId: api.id,
    routeKey: "POST /users",
    target: pulumi.interpolate`integrations/${integration.id}`,
});

// Stage
const stage = new aws.apigatewayv2.Stage("default", {
    apiId: api.id,
    name: "$default",
    autoDeploy: true,
});

// Lambda permission
const permission = new aws.lambda.Permission("api-permission", {
    action: "lambda:InvokeFunction",
    function: handler.name,
    principal: "apigateway.amazonaws.com",
    sourceArn: pulumi.interpolate`${api.executionArn}/*/*`,
});

export const apiUrl = api.apiEndpoint;

Use when: Serverless REST APIs, microservices

Pattern 3: Global Content Delivery

CloudFront + S3 + Route 53

// S3 bucket for website
const bucket = new aws.s3.BucketV2("website", {
    bucket: "my-website.com",
});

// Origin Access Identity for CloudFront
const oai = new aws.cloudfront.OriginAccessIdentity("oai", {
    comment: "OAI for website bucket",
});

// Bucket policy to allow CloudFront
const bucketPolicy = new aws.s3.BucketPolicy("bucket-policy", {
    bucket: bucket.id,
    policy: pulumi.all([bucket.arn, oai.iamArn]).apply(([bucketArn, oaiArn]) =>
        JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { AWS: oaiArn },
                Action: "s3:GetObject",
                Resource: `${bucketArn}/*`,
            }],
        })
    ),
});

// ACM certificate for CloudFront (must be in us-east-1)
const certificate = new aws.acm.Certificate("cert", {
    domainName: "my-website.com",
    validationMethod: "DNS",
}, { provider: usEast1Provider });

// CloudFront distribution
const cdn = new aws.cloudfront.Distribution("cdn", {
    origins: [{
        domainName: bucket.bucketRegionalDomainName,
        originId: "S3Origin",
        s3OriginConfig: {
            originAccessIdentity: oai.cloudfrontAccessIdentityPath,
        },
    }],
    enabled: true,
    defaultRootObject: "index.html",
    aliases: ["my-website.com", "www.my-website.com"],
    defaultCacheBehavior: {
        targetOriginId: "S3Origin",
        viewerProtocolPolicy: "redirect-to-https",
        allowedMethods: ["GET", "HEAD", "OPTIONS"],
        cachedMethods: ["GET", "HEAD"],
        forwardedValues: {
            queryString: false,
            cookies: { forward: "none" },
        },
        compress: true,
        minTtl: 0,
        defaultTtl: 3600,
        maxTtl: 86400,
    },
    restrictions: {
        geoRestriction: { restrictionType: "none" },
    },
    viewerCertificate: {
        acmCertificateArn: certificate.arn,
        sslSupportMethod: "sni-only",
        minimumProtocolVersion: "TLSv1.2_2021",
    },
});

// Route 53 records
const zone = aws.route53.getZone({ name: "my-website.com" });

const record = new aws.route53.Record("website", {
    zoneId: zone.then(z => z.zoneId),
    name: "my-website.com",
    type: "A",
    aliases: [{
        name: cdn.domainName,
        zoneId: cdn.hostedZoneId,
        evaluateTargetHealth: false,
    }],
});

export const websiteUrl = pulumi.interpolate`https://${record.name}`;

Use when: Static websites, global applications, CDN requirements

Pattern 4: Multi-Region Failover

Route 53 + Health Checks

// Primary region ALB (us-east-1)
const primaryAlb = new aws.lb.LoadBalancer("primary-alb", {
    loadBalancerType: "application",
    subnets: primarySubnetIds,
}, { provider: usEast1Provider });

// Secondary region ALB (us-west-2)
const secondaryAlb = new aws.lb.LoadBalancer("secondary-alb", {
    loadBalancerType: "application",
    subnets: secondarySubnetIds,
}, { provider: usWest2Provider });

// Health check for primary
const primaryHealthCheck = new aws.route53.HealthCheck("primary-health", {
    type: "HTTPS",
    resourcePath: "/health",
    fqdn: primaryAlb.dnsName,
    port: 443,
    requestInterval: 30,
    failureThreshold: 3,
    tags: { Name: "primary-health-check" },
});

// Route 53 records with failover
const zone = aws.route53.getZone({ name: "example.com" });

const primaryRecord = new aws.route53.Record("primary", {
    zoneId: zone.then(z => z.zoneId),
    name: "app.example.com",
    type: "A",
    setIdentifier: "primary",
    failoverRoutingPolicies: [{ type: "PRIMARY" }],
    healthCheckId: primaryHealthCheck.id,
    aliases: [{
        name: primaryAlb.dnsName,
        zoneId: primaryAlb.zoneId,
        evaluateTargetHealth: true,
    }],
});

const secondaryRecord = new aws.route53.Record("secondary", {
    zoneId: zone.then(z => z.zoneId),
    name: "app.example.com",
    type: "A",
    setIdentifier: "secondary",
    failoverRoutingPolicies: [{ type: "SECONDARY" }],
    aliases: [{
        name: secondaryAlb.dnsName,
        zoneId: secondaryAlb.zoneId,
        evaluateTargetHealth: true,
    }],
});

export const appUrl = "https://app.example.com";

Use when: High availability, disaster recovery, multi-region

Pattern 5: Hybrid Connectivity

Transit Gateway + VPN

// Transit Gateway
const tgw = new aws.ec2transitgateway.TransitGateway("main-tgw", {
    description: "Main transit gateway",
    amazonSideAsn: 64512,
    defaultRouteTableAssociation: "enable",
    defaultRouteTablePropagation: "enable",
    tags: { Name: "main-tgw" },
});

// VPC attachments
const vpcAttachment1 = new aws.ec2transitgateway.VpcAttachment("vpc1-attachment", {
    transitGatewayId: tgw.id,
    vpcId: vpc1.id,
    subnetIds: vpc1PrivateSubnetIds,
    tags: { Name: "vpc1-attachment" },
});

const vpcAttachment2 = new aws.ec2transitgateway.VpcAttachment("vpc2-attachment", {
    transitGatewayId: tgw.id,
    vpcId: vpc2.id,
    subnetIds: vpc2PrivateSubnetIds,
    tags: { Name: "vpc2-attachment" },
});

// Customer Gateway (on-premises)
const cgw = new aws.ec2.CustomerGateway("on-prem-cgw", {
    bgpAsn: 65000,
    ipAddress: "203.0.113.1", // On-premises public IP
    type: "ipsec.1",
    tags: { Name: "on-premises-cgw" },
});

// VPN attachment to Transit Gateway
const vpnAttachment = new aws.ec2transitgateway.VpnAttachment("vpn-attachment", {
    transitGatewayId: tgw.id,
    vpnConnectionId: vpnConnection.id,
    tags: { Name: "vpn-attachment" },
});

// Site-to-Site VPN
const vpnConnection = new aws.ec2.VpnConnection("vpn", {
    customerGatewayId: cgw.id,
    transitGatewayId: tgw.id,
    type: "ipsec.1",
    staticRoutesOnly: false, // Use BGP
    tags: { Name: "site-to-site-vpn" },
});

export const tgwId = tgw.id;

Use when: Multiple VPCs, hybrid cloud, centralized routing

Performance Guidelines

ALB/NLB Performance

  • ALB: 50,000+ requests/sec per AZ
  • NLB: Millions of requests/sec, ultra-low latency
  • Use cross-zone load balancing for even distribution
  • Enable connection draining for graceful shutdowns
  • Configure appropriate health check intervals

CloudFront Performance

  • 225+ edge locations worldwide
  • Sub-100ms latency for 99% of requests
  • Use regional edge caches for less popular content
  • Enable compression for text content
  • Implement cache key optimization

API Gateway Performance

  • REST API: 10,000 requests/sec (default, can increase)
  • HTTP API: Lower latency, up to 60% cheaper
  • Use caching to reduce backend load
  • Implement throttling to protect backends
  • Use Lambda proxy integration for simplicity

Cost Optimization

VPC Cost Reduction

  1. Delete unused NAT Gateways - $0.045/hour (~$32/month each)
  2. Use VPC endpoints - Avoid NAT Gateway data charges for AWS services
  3. Consolidate NAT Gateways - One per region (not per AZ) for dev/test
  4. Delete unused Elastic IPs - $0.005/hour when not associated

Load Balancer Cost Reduction

  1. Use ALB instead of Classic LB - Better features, often cheaper
  2. Delete unused load balancers - $0.0225/hour + data processed
  3. Use NLB for static IPs - More cost-effective than EIP per instance
  4. Consolidate load balancers - Use host/path routing instead of multiple ALBs

CloudFront Cost Reduction

  1. Enable compression - Reduce data transfer costs
  2. Use appropriate TTLs - Reduce origin requests
  3. Implement cache hierarchies - Use Lambda@Edge sparingly
  4. Use S3 Transfer Acceleration - For large uploads only when needed
  5. Monitor CloudFront reports - Identify optimization opportunities

API Gateway Cost Reduction

  1. Use HTTP API instead of REST - Up to 60% cheaper
  2. Implement caching - Reduce backend invocations
  3. Use appropriate throttling - Prevent unnecessary costs
  4. Delete unused APIs - Regular cleanup
  5. Use regional endpoints - Edge-optimized costs more

Quick Links

Core Services

  • VPC - Virtual Private Cloud
  • Load Balancers - ALB, NLB
  • Route 53 - DNS Service
  • CloudFront - CDN
  • API Gateway - REST APIs
  • API Gateway v2 - HTTP/WebSocket

Related Services

Guides

See Also

Install with Tessl CLI

npx tessl i tessl/npm-pulumi--aws

docs

index.md

quickstart.md

README.md

tile.json