You spent a week configuring Serverless Framework, and at the first deploy Lambda functions don't start – error 502, CloudWatch empty. Sound familiar? We have deployed 50+ serverless projects on AWS, GCP, and Azure, and each time we encountered the same pitfalls: misconfigured IAM roles, forgotten environment variables, and oversized builds causing high cold start. According to our data, a properly tuned serverless stack reduces infrastructure costs by 3–5 times, but only if the configuration is flawless. For example, after migrating an e-commerce platform, monthly infrastructure costs dropped from $800 to $200, a 75% savings. In this article, we break down every step from installation to CI/CD, with real configurations and battle‑tested practices. You'll learn how to avoid typical mistakes, shave 40% off cold start times, and organize secure secret storage. We draw on experience from 50+ projects and keep our configs up to date with the latest plugin and runtime versions. Our team holds AWS Certified Solutions Architect certifications and has over 5 years of hands-on serverless experience. We guarantee a cold start reduction of at least 40% with our optimized configuration.
Serverless Framework Setup
Step-by-Step Setup
- Install Serverless Framework globally:
npm install -g serverless - Create a new service:
serverless create --template aws-nodejs-typescript --path my-service - Navigate into the service and install dependencies:
cd my-service && npm install - Configure
serverless.ymlwith provider, plugins, and functions. - Deploy for the first time:
serverless deploy --stage dev
The project structure includes a src/functions/ folder for handlers and src/libs/ for helper modules. The serverless.yml file is the heart of the configuration.
What Is Cold Start and How to Beat It?
Cold start is the time from the first request to the handler execution, caused by the runtime initialization and code loading. Our tests show that with a non‑optimized bundle, cold start can reach 500 ms. Use esbuild with tree shaking – it reduces the bundle size by 60% and drops cold start from 450ms to 120ms (a 73% improvement). Exclude built‑in dependencies like @aws-sdk/*, which are already present in the Lambda environment. For latency‑sensitive functions, enable Provisioned Concurrency (up to 3× cost, but cold start = 0). Unlike webpack, esbuild is 10–100 times faster and offers serverless-native bundling.
Proper serverless.yml Configuration
service: my-web-service
frameworkVersion: '3'
plugins:
- serverless-esbuild
- serverless-offline
- serverless-dotenv-plugin
provider:
name: aws
runtime: nodejs20.x
region: eu-west-1
stage: ${opt:stage, 'dev'}
memorySize: 512
timeout: 10
logRetentionInDays: 14
environment:
NODE_ENV: ${self:provider.stage}
DB_PASSWORD: ${ssm:/my-service/${self:provider.stage}/db-password~true}
API_KEY: ${ssm:/my-service/api-key~true}
iam:
role:
statements:
- Effect: Allow
Action: [s3:GetObject, s3:PutObject]
Resource: 'arn:aws:s3:::${self:custom.bucketName}/*'
- Effect: Allow
Action: [dynamodb:Query, dynamodb:PutItem, dynamodb:UpdateItem]
Resource: !GetAtt UsersTable.Arn
httpApi:
cors:
allowedOrigins: ['https://my-site.com', 'http://localhost:3000']
allowedHeaders: ['Content-Type', 'Authorization']
allowedMethods: [GET, POST, PUT, DELETE]
custom:
bucketName: my-service-${self:provider.stage}-assets
esbuild:
bundle: true
minify: ${strToBool(${ssm:/my-service/minify, 'false'})}
sourcemap: true
target: node20
platform: node
concurrency: 10
external:
- '@aws-sdk/*'
- 'pg-native'
serverless-offline:
httpPort: 3001
lambdaPort: 3002
functions:
- ${file(src/functions/api/index.ts)}
- ${file(src/functions/worker/index.ts)}
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-${self:provider.stage}-users
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: pk
AttributeType: S
- AttributeName: sk
AttributeType: S
KeySchema:
- AttributeName: pk
KeyType: HASH
- AttributeName: sk
KeyType: RANGE
TimeToLiveSpecification:
AttributeName: ttl
Enabled: true
Function Configuration and Middleware
// src/functions/api/index.ts
import type { AWS } from '@serverless/typescript';
const apiFunction: AWS['functions'] = {
api: {
handler: 'src/functions/api/handler.main',
events: [{
httpApi: {
method: 'ANY',
path: '/api/{proxy+}',
authorizer: {
name: 'jwtAuthorizer',
type: 'jwt',
identitySource: '$request.header.Authorization',
issuerUrl: 'https://cognito-idp.eu-west-1.amazonaws.com/${env:COGNITO_POOL_ID}',
audience: ['${env:COGNITO_CLIENT_ID}'],
},
},
}],
environment: {},
},
};
export default apiFunction;
// src/libs/lambda.ts
import middy from '@middy/core';
import middyJsonBodyParser from '@middy/http-json-body-parser';
import httpErrorHandler from '@middy/http-error-handler';
import cors from '@middy/http-cors';
import type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from 'aws-lambda';
type Handler = (event: APIGatewayProxyEventV2) => Promise<APIGatewayProxyStructuredResultV2>;
export const middyfy = (handler: Handler) =>
middy(handler)
.use(middyJsonBodyParser())
.use(httpErrorHandler())
.use(cors({ origin: process.env.ALLOWED_ORIGIN ?? '*' }));
How to Manage Environments Efficiently?
Use different stages and SSM Parameter Store for secure secret storage. Encrypted parameters use the ~true suffix. For local development, run serverless offline start; to test a specific function, use serverless invoke local --function. Never store secrets in Git – this is one of the most common mistakes leading to data leaks.
Why esbuild Is the Best Choice for Bundling?
According to the AWS Serverless Developer Guide, esbuild with tree shaking reduces bundle size by up to 40% and lowers cold start. Unlike webpack, it is 10–100 times faster and requires no complex configuration. For native libraries like sharp, create a Lambda Layer – this keeps them separate and updates independent.
mkdir -p layer/nodejs
cd layer/nodejs
npm install sharp
Attach the layer:
layers:
sharp:
path: layer
compatibleRuntimes: [nodejs20.x]
Real‑World Impact: Cold Start and Cost Reduction
In one project for an e‑commerce platform, we reduced the cold start from 450 ms to 120 ms (73% improvement) by using esbuild with tree shaking and moving large dependencies (like sharp) to a Lambda Layer. The monthly infrastructure cost dropped by 75% compared to their previous VPS setup, saving $600 per month, while scaling seamlessly during flash sales.
Comparison: Serverless vs VPS
| Criteria | Serverless (Lambda) | VPS (Nginx + Node) |
|---|---|---|
| Scaling | Automatic | Manual (auto-scaling) |
| Idle cost | ~0 | Pay for resources |
| Cold start | 100‑500 ms | 0 ms |
| Max execution time | 15 min | No limit |
| Infrastructure upkeep | Provider | You do it |
Under unpredictable load, serverless saves up to 5× compared to VPS. Serverless auto-scaling is infinitely better than manual scaling during traffic spikes. For sustained traffic above 1000 req/s, VPS may be cheaper.
Popular Serverless Framework Plugins
| Plugin | Purpose |
|---|---|
| serverless-esbuild | Fast bundling with tree shaking |
| serverless-offline | Local emulation of Lambda & API Gateway |
| serverless-dotenv-plugin | Load .env files |
| serverless-ssm-fetch | Auto‑fetch parameters from SSM |
CI/CD for Serverless Framework
Set up GitHub Actions or GitLab CI for automatic deployments to different stages. In the workflow, include steps: checkout, install dependencies, and deploy via npx serverless deploy --stage prod. Store secrets in GitHub Secrets or GitLab CI Variables. A typical pipeline dev → staging → prod takes 2–3 minutes.
What’s Included in Your Serverless Framework Setup?
-
serverless.ymlconfiguration with IAM, VPC, and environments - Build optimization (esbuild, tree shaking, Lambda Layers)
- CI/CD pipeline (GitHub Actions / GitLab CI) for dev/staging/prod
- Secret management via SSM or Secrets Manager
- Comprehensive architectural diagram and documentation
- Access to full repository with configuration
- Team training
- Post‑deploy support (24/7 during transition)
- Guaranteed cold start reduction of at least 40%
Timelines
Basic setup with one function and deployment – 1 day. Full infrastructure with multiple functions, DynamoDB, SSM, and CI/CD – 3–4 days. Migration from Express – 1–2 weeks. Pricing is determined individually based on complexity and scope.
Contact us for a free serverless architecture audit. Get a consultation on Serverless Framework setup – we’ll help you avoid common mistakes and accelerate development.







