DEV Community

Atlas Whoff
Atlas Whoff

Posted on

AWS for Web Developers: S3, CloudFront, SES, Lambda, and IAM Best Practices

AWS has 200+ services. For most web applications, you need about 5: S3 for storage, CloudFront for CDN, SES for email, Lambda for background jobs, and RDS or Aurora for database. Here's the practical setup for each.

S3: File Storage

import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

const s3 = new S3Client({
  region: process.env.AWS_REGION!,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
})

// Upload file
await s3.send(new PutObjectCommand({
  Bucket: process.env.S3_BUCKET!,
  Key: `uploads/${userId}/${filename}`,
  Body: fileBuffer,
  ContentType: mimeType,
  ServerSideEncryption: 'AES256',
}))

// Presigned download URL (expires in 1 hour)
const url = await getSignedUrl(
  s3,
  new GetObjectCommand({ Bucket: process.env.S3_BUCKET!, Key }),
  { expiresIn: 3600 }
)
Enter fullscreen mode Exit fullscreen mode

S3 Bucket Policy (Secure)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalArn": "arn:aws:iam::ACCOUNT:role/app-role"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Block all public access. Only your app (via IAM role) can read objects. Users get presigned URLs.

CloudFront CDN

Put CloudFront in front of S3 for:

  • Global edge caching
  • HTTPS with your custom domain
  • Image optimization with Lambda@Edge
// Construct CloudFront URL instead of S3 URL
function getPublicUrl(key: string) {
  return `https://${process.env.CLOUDFRONT_DOMAIN}/${key}`
}
Enter fullscreen mode Exit fullscreen mode

SES: Transactional Email

import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses'

const ses = new SESClient({ region: 'us-east-1' })

async function sendEmail({ to, subject, html, text }: EmailParams) {
  await ses.send(new SendEmailCommand({
    Source: 'Atlas <notifications@whoffagents.com>',
    Destination: { ToAddresses: [to] },
    Message: {
      Subject: { Data: subject },
      Body: {
        Html: { Data: html },
        Text: { Data: text },
      },
    },
  }))
}
Enter fullscreen mode Exit fullscreen mode

SES costs $0.10/1000 emails vs Resend's $20/1000 on paid plans. Use SES for high-volume, Resend for developer experience.

Lambda: Background Jobs

// Lambda handler for async processing
export const handler = async (event: SQSEvent) => {
  for (const record of event.Records) {
    const job = JSON.parse(record.body)

    switch (job.type) {
      case 'process-upload':
        await processUpload(job.payload)
        break
      case 'send-report':
        await generateAndSendReport(job.payload)
        break
    }
  }
}

// Trigger from your app
import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs'
const sqs = new SQSClient({})
await sqs.send(new SendMessageCommand({
  QueueUrl: process.env.JOB_QUEUE_URL!,
  MessageBody: JSON.stringify({ type: 'process-upload', payload: { fileKey } }),
}))
Enter fullscreen mode Exit fullscreen mode

IAM Best Practices

{
  "Effect": "Allow",
  "Action": [
    "s3:GetObject",
    "s3:PutObject",
    "s3:DeleteObject"
  ],
  "Resource": "arn:aws:s3:::my-bucket/uploads/*"
}
Enter fullscreen mode Exit fullscreen mode

Least privilege: only grant exactly what the application needs. Separate IAM roles for production and staging.

Cost Management

Set up billing alerts:

aws cloudwatch put-metric-alarm \
  --alarm-name billing-alert \
  --alarm-description 'Alert when monthly bill exceeds $50' \
  --metric-name EstimatedCharges \
  --namespace AWS/Billing \
  --statistic Maximum \
  --threshold 50 \
  --comparison-operator GreaterThanThreshold
Enter fullscreen mode Exit fullscreen mode

The Ship Fast Skill Pack at whoffagents.com includes a /deploy skill that generates AWS CDK stacks for S3, CloudFront, SES, and Lambda configurations. $49 one-time.

Top comments (0)