Most JavaScript developers can build features. Far fewer can ship and operate them in production. The difference between a $120K developer and a $160K developer is usually the ability to deploy, scale, and monitor their own infrastructure.
Here are six AWS patterns modern JavaScript teams use to run production systems without a dedicated DevOps engineer.
Lambda Functions Replace Node Servers
Traditional Node APIs run on a server you maintain. That means patching the OS, scaling instances, and handling downtime.
Before
import express from "express"
import { PrismaClient } from "@prisma/client"
const app = express()
const prisma = new PrismaClient()
app.get("/jobs", async (req, res) => {
const jobs = await prisma.jobPosting.findMany({
orderBy: { createdAt: "desc" },
take: 20
})
res.json(jobs)
})
app.listen(3000)
After
import { APIGatewayProxyEvent } from "aws-lambda"
import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient()
export const handler = async (event: APIGatewayProxyEvent) => {
const jobs = await prisma.jobPosting.findMany({
orderBy: { createdAt: "desc" },
take: 20
})
return {
statusCode: 200,
body: JSON.stringify(jobs)
}
}
Lambda removes server management entirely. The function runs only when invoked and scales automatically. A small production API often costs under $10 per month while handling millions of requests.
API Gateway Turns Functions Into Production APIs
Lambda functions do not expose HTTP endpoints on their own. API Gateway handles routing, authentication, rate limits, and CORS.
Before
app.post("/applications", async (req, res) => {
const application = await prisma.application.create({
data: req.body
})
res.json(application)
})
After
functions:
createApplication:
handler: lambda/createApplication.handler
events:
- http:
path: /applications
method: post
cors: true
With one configuration block, API Gateway exposes the Lambda function as a public REST endpoint.
You also gain throttling, authentication layers, and request validation without writing middleware.
S3 Replaces File Servers
Many Node applications store uploaded files on the same server running the API. That approach breaks once you scale horizontally.
Before
import fs from "fs"
export async function uploadResume(file, filename) {
const path = `uploads/${Date.now()}-${filename}`
fs.writeFileSync(path, file)
return path
}
After
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"
const s3 = new S3Client({ region: "us-east-1" })
export async function uploadResume(file: Buffer, filename: string) {
const key = `resumes/${Date.now()}-${filename}`
await s3.send(new PutObjectCommand({
Bucket: "developer-resumes",
Key: key,
Body: file,
ContentType: "application/pdf"
}))
return `https://developer-resumes.s3.amazonaws.com/${key}`
}
S3 is globally durable storage. Storing 10 GB of files costs roughly twenty cents per month. Scaling storage is no longer part of your architecture problem.
SQS Moves Slow Work Out of Your API
Sending emails, generating PDFs, and updating analytics inside an API request slows everything down.
Queues decouple the request from the heavy work.
Before
app.post("/apply", async (req, res) => {
await prisma.application.create({ data: req.body })
await sendEmail(req.body.companyEmail)
await updateAnalytics(req.body.jobId)
res.json({ success: true })
})
After
import { SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs"
const sqs = new SQSClient({ region: "us-east-1" })
export async function queueApplication(data) {
await sqs.send(new SendMessageCommand({
QueueUrl: process.env.APPLICATION_QUEUE,
MessageBody: JSON.stringify(data)
}))
}
A separate Lambda consumes the queue and processes tasks asynchronously. Your API responds in milliseconds instead of seconds.
This pattern also prevents lost work if a worker crashes.
CloudFront Makes Your App Fast Worldwide
Serving static assets directly from your origin server creates huge latency for global users.
A CDN caches assets near users.
Before
User -> US server -> React bundle
After
User -> CloudFront edge -> cached React bundle
Example configuration:
const distribution = {
Origins: [{
DomainName: "frontend-assets.s3.amazonaws.com"
}],
DefaultCacheBehavior: {
ViewerProtocolPolicy: "redirect-to-https",
Compress: true
}
}
For international traffic this often reduces page load time by 40 to 60 percent.
Infrastructure as Code Replaces Manual AWS Setup
Many developers configure AWS through the console. That makes infrastructure impossible to reproduce.
Infrastructure should live in your repository.
Before
Manual setup steps
1. Create Lambda
2. Create API Gateway
3. Attach permissions
4. Configure environment variables
After
import { Stack } from "aws-cdk-lib"
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs"
import * as apigateway from "aws-cdk-lib/aws-apigateway"
export class ApiStack extends Stack {
constructor(scope, id) {
super(scope, id)
const getJobs = new NodejsFunction(this, "GetJobs", {
entry: "lambda/getJobs.ts"
})
const api = new apigateway.RestApi(this, "Api")
api.root.addResource("jobs").addMethod(
"GET",
new apigateway.LambdaIntegration(getJobs)
)
}
}
The entire infrastructure becomes version controlled code.
Changes go through pull requests just like application logic.
If you want to go deeper on the deployment side, the production pipeline described in the CI/CD pipeline patterns JavaScript teams use in production shows how teams automate these deployments.
Structured Logging Makes Serverless Debuggable
When you cannot SSH into servers, logs become your only debugging tool.
Structured logging makes them searchable.
Before
console.log("Fetching jobs")
console.log(jobs)
After
function log(level: string, message: string, data = {}) {
console.log(JSON.stringify({
level,
message,
timestamp: new Date().toISOString(),
...data
}))
}
log("info", "Jobs fetched", {
count: jobs.length,
duration: Date.now() - startTime
})
With structured logs you can query production behavior using CloudWatch Insights and identify bottlenecks quickly.
Developers who know React and Node can build applications. Developers who know these AWS patterns can run them in production. That difference is why companies increasingly expect JavaScript engineers to own infrastructure as well as code.
Pick one of these patterns and implement it in a small side project this week. Once you deploy your own serverless API, cloud architecture stops feeling abstract and starts feeling like a normal part of development.
Top comments (0)