The "Quick" Start Reality Check
The marketing says "deploy in minutes" but here's what actually happens:
Prerequisites:
- Node.js 18+ (version 14 breaks with cryptic errors about OpenSSL)
- AWS CLI configured with proper credentials (half your problems will be IAM)
- Basic familiarity with YAML configuration (and the subtle indentation hell that awaits)
Installation and First Deployment:
## Install globally (or don't, npx works too)
npm install -g serverless
## Create from template (this part actually works)
serverless create --template aws-nodejs --path my-first-service
cd my-first-service
## Deploy and pray
serverless deploy
What actually happens on first deploy:
- It works perfectly (if you're lucky - happened to me once in 2019)
- CloudFormation sits there for 10 minutes then dies with some useless error (happens constantly)
- IAM permission error that I've spent 2+ hours debugging every single time (pro tip: check the region)
- Region quota limit because you forgot Lambda has a 1000 concurrent execution limit (learned this at 2 AM during a demo)
- Random network error that magically fixes itself on retry (because AWS infrastructure is held together with hope and duct tape)
The official tutorial is great until you try to add DynamoDB or SQS, then you're on your own.
Configuration That Actually Works
The anatomy of a serverless.yml file - simpler than CloudFormation, more complex than it should be
The serverless.yml That Won't Break:
service: my-service
provider:
name: aws
runtime: nodejs18.x
region: us-east-1
# Set this or your functions will timeout randomly
timeout: 30
# Set this to 1GB or spend hours optimizing for 12 cents/month savings
memorySize: 1024
functions:
hello:
handler: handler.hello
events:
- http:
path: /hello
method: get
# Enable CORS or your frontend will hate you
cors: true
resources:
Resources:
MyDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
# Don't use the service name in table names, it gets truncated
TableName: ${self:service}-${opt:stage, 'dev'}-my-table
BillingMode: PAY_PER_REQUEST
Cold Start Reality:
- Function startup times vary from 100ms to several seconds depending on runtime and dependencies
- Provisioned concurrency costs more than your Lambda executions (not worth it unless you're Netflix)
- Connection pooling helps but adds complexity
- AWS SDK v3 supposedly reduced cold starts by 200ms (I couldn't measure the difference but whatever)
Memory and Timeout Settings:
- Memory: 1GB is a reasonable default for most functions
- Timeout: Set it to 30 seconds minimum or random requests will fail
- Maximum timeout: 15 minutes, then your function dies anyway
- Monitor CloudWatch if you want, but the metrics lag behind reality
Bundling Hell:
- Webpack breaks more things than it fixes (use esbuild instead)
- Lambda layers are great until you need to update them across 50 functions
- The webpack plugin is abandoned, use serverless-esbuild
Security Best Practices (That You'll Probably Get Wrong)
IAM Permissions:
- Serverless generates basic IAM policies that work for most use cases
- Complex permissions may require custom IAM policy configuration
- IAM policy conditions are great in theory, nightmare to debug in practice
- Just give your function the permissions it needs and tune later
Secrets Management:
- Parameter Store is free but slow (200ms+ latency)
- Secrets Manager costs money but rotates automatically
- Environment variables are encrypted at rest but visible in the console
- Most teams hardcode secrets initially, refactor later (don't tell security)
VPC Configuration (Don't Do It Unless You Must):
- VPC Lambda functions have 10x worse cold starts (seriously, avoid)
- VPC endpoints cost about $50/month each
- You probably don't need VPC unless compliance requires it
- If you must use VPC, prepare for deployment timeouts and networking hell
Monitoring (When Things Break at 3AM)
CloudWatch Metrics:
- Built-in CloudWatch metrics are basic but free
- CloudWatch alarms trigger 5+ minutes after the problem - found out our API was down when customers started calling, not from alerts
- X-Ray tracing helps but adds latency to every request (and costs way more than you think)
- Custom metrics cost money and require extra code

CloudWatch metrics that tell you something broke 5 minutes too late

A typical serverless CI/CD pipeline - more complex than your actual application
Real-World Monitoring:
- Use Sentry for error tracking (actually useful)
- Datadog is expensive but actually shows you what's broken
- CloudWatch Logs cost more than your Lambda executions if you log everything
- Most teams use console.log and grep through CloudWatch (works fine)
CI/CD Integration (Prepare for Pipeline Hell)
Deployment Strategies That Actually Work:
- Staged deployments work great until CloudFormation randomly fails
- Testing before deployment is smart but most teams deploy to dev and pray
- Separate AWS accounts prevent dev from breaking prod (definitely do this)
A typical serverless CI/CD pipeline - more complex than your actual application
Pipeline Configuration:
## GitHub Actions that will break eventually
- name: Deploy to AWS
run: |
# Timeout after 20 minutes or GitHub Actions kills it
timeout 1200 serverless deploy --stage production
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Common Pitfalls (You'll Hit All of These)
Things That Will Break:
- Plugin version conflicts - Pin ALL plugin versions or wake up to "Cannot read property 'map' of undefined" errors
- CloudFormation resource limits - 500 resource max hits you with "Template format error: Number of resources exceeded limit"
- IAM eventual consistency - New roles take 10-60 seconds to propagate, causing "The role defined for the function cannot be assumed by Lambda" failures
- Node.js 18+ webpack plugin issues - I spent 4 hours debugging "Cannot find module 'webpack/lib/node/NodeTemplatePlugin'" errors before realizing serverless-webpack doesn't play nice with newer Node versions (just use serverless-esbuild instead)
- Timeout inconsistencies - API Gateway timeout (30s) vs Lambda timeout (15m) means your function runs but times out at the gateway
Testing Reality:
Cost Surprises:

AWS Lambda pricing - simpler than the hidden costs you'll discover later
The harsh truth: Start simple, accept that things will break, and have rollback plans. Every serverless deployment is gambling that CloudFormation will work today.