Amazon S3

Has Demo

Simple Storage Service - Store and retrieve any amount of data

💵 Cost: S3 Free Tier includes 5GB storage, 20,000 GET, 2,000 PUT requests/month for 12 months. Empty buckets cost nothing. Delete all objects before deleting a bucket. See our Costs & Cleanup Guide for cleanup steps.

What is S3?

Amazon Simple Storage Service (S3) is object storage for the cloud. Think of it as an unlimited hard drive accessible from anywhere via HTTP. Store files, images, videos, backups, logs - anything you need.

S3 is Everywhere

S3 is one of the most used AWS services. Its used for static website hosting, data lakes, backup storage, content distribution, and much more. Understanding S3 is fundamental to working with AWS.

S3 Concepts

ConceptDescriptionExample
BucketContainer for objects (like a folder)my-app-uploads
ObjectFile + metadatausers/123/avatar.jpg
KeyUnique identifier for an objectuploads/2024/01/report.pdf
PrefixKey path for organization (like folders)uploads/2024/01/

Create a Bucket

Terminal
$aws s3 mb s3://my-unique-bucket-name-12345 --region ap-southeast-1
make_bucket: my-unique-bucket-name-12345

Bucket Names are Global

S3 bucket names must be globally unique across ALL AWS accounts. Use your company name or project as a prefix to avoid conflicts.

Upload a File

TypeScript
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"

const s3 = new S3Client({ region: process.env.AWS_REGION })

export async function uploadFile(
  file: Buffer,
  key: string,
  contentType: string
) {
  const command = new PutObjectCommand({
    Bucket: process.env.S3_BUCKET_NAME,
    Key: key,
    Body: file,
    ContentType: contentType
  })

  await s3.send(command)

  return `https://${process.env.S3_BUCKET_NAME}.s3.amazonaws.com/${key}`
}

List Objects

TypeScript
import { ListObjectsV2Command } from "@aws-sdk/client-s3"

export async function listFiles(prefix?: string) {
  const command = new ListObjectsV2Command({
    Bucket: process.env.S3_BUCKET_NAME,
    Prefix: prefix,
    MaxKeys: 100
  })

  const response = await s3.send(command)

  return response.Contents?.map(obj => ({
    key: obj.Key,
    size: obj.Size,
    lastModified: obj.LastModified
  })) ?? []
}

Generate Presigned URL

Presigned URLs allow temporary access to private objects without exposing credentials:

TypeScript
import { GetObjectCommand } from "@aws-sdk/client-s3"
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"

export async function getDownloadUrl(key: string) {
  const command = new GetObjectCommand({
    Bucket: process.env.S3_BUCKET_NAME,
    Key: key
  })

  // URL valid for 1 hour
  const url = await getSignedUrl(s3, command, { expiresIn: 3600 })

  return url
}

Try the Demo

Check out the live S3 demo to upload files, list bucket contents, and generate download links.

Storage Classes

ClassUse CaseCost
StandardFrequently accessed data$0.023/GB
Intelligent-TieringUnknown access patternsAuto-optimized
GlacierArchive (retrieval in minutes)$0.004/GB
Glacier Deep ArchiveLong-term archive (retrieval in hours)$0.00099/GB

S3 Pricing

Region-Specific Pricing

Prices shown are for ap-southeast-1 (Singapore). Prices vary by region. Always verify at aws.amazon.com/s3/pricing. Last verified: January 2026.
ComponentCost (ap-southeast-1)
Storage (Standard)$0.023/GB/month
PUT/POST requests$0.005 per 1,000
GET requests$0.0004 per 1,000
Data transfer out$0.09/GB (first 10TB)

Cost Optimization

For images and static assets, use CloudFront CDN in front of S3. This reduces S3 request costs and speeds up delivery globally.

AWS Deployment Guide — Built with Next.js