Вы потратили неделю на настройку Serverless Framework, а при первом деплое Lambda функции не стартуют — ошибка 502, в CloudWatch пусто. Знакомо? Мы развернули 50+ serverless-проектов на AWS, GCP и Azure, и каждый раз сталкивались с одними и теми же граблями: кривые IAM-роли, забытые переменные окружения, неоптимальная сборка с гигантским cold start. По нашим данным, правильно настроенный serverless-стек снижает затраты на инфраструктуру в 3–5 раз, но только если конфигурация выполнена без ошибок. В этой статье мы разберём каждый шаг: от установки до CI/CD, с реальными конфигурациями и проверенными практиками. Вы узнаете, как избежать типичных ошибок, ускорить холодный старт на 40% и организовать безопасное хранение секретов. Мы опираемся на опыт 50+ проектов и постоянно обновляем конфигурации под последние версии плагинов и runtime.
Как настроить Serverless Framework за 1 день?
Установка и базовая структура
npm install -g serverless
serverless --version # 3.x или 4.x
serverless create --template aws-nodejs-typescript --path my-service
cd my-service
npm install
Структура проекта включает папку src/functions/ с обработчиками и src/libs/ для вспомогательных модулей. Файл serverless.yml — сердце конфигурации.
Что такое холодный старт и как с ним бороться?
Холодный старт — время от первого запроса до выполнения handler'а, вызванное инициализацией runtime и загрузкой кода. Наши тесты показывают, что при неоптимальной сборке cold start достигает 500 мс. Используйте esbuild с tree shaking — это уменьшает бандл на 30% и снижает холодный старт до 100-200 мс. Исключайте встроенные зависимости, такие как @aws-sdk/*, которые уже есть в окружении Lambda. Для функций с высокими требованиями к скорости применяйте Provisioned Concurrency (до 300% стоимости, но cold start = 0).
serverless.yml — правильная конфигурация
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
Конфигурация функции и 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 ?? '*' }));
Как управлять окружениями эффективно?
Используйте разные стейджи и SSM Parameter Store для безопасного хранения секретов. Параметры с шифрованием добавляются суффиксом ~true. Для локальной разработки запускайте serverless offline start, а для тестирования отдельной функции — serverless invoke local --function. Не храните секреты в Git — это одна из самых частых ошибок, приводящих к утечкам.
Почему esbuild — лучший выбор для сборки?
По данным AWS Serverless Developer Guide, esbuild с tree shaking уменьшает размер бандла до 40% и снижает cold start. В отличие от webpack, он работает в 10-100 раз быстрее и не требует сложной конфигурации. Для native-библиотек, таких как sharp, создавайте Lambda Layer — это позволяет держать их отдельно и обновлять независимо.
mkdir -p layer/nodejs
cd layer/nodejs
npm install sharp
Подключение слоя:
layers:
sharp:
path: layer
compatibleRuntimes: [nodejs20.x]
Сравнение Serverless vs VPS
| Критерий | Serverless (Lambda) | VPS (Nginx + Node) |
|---|---|---|
| Масштабирование | Автоматическое | Ручное (auto-scaling) |
| Стоимость на простое | ~0 | Оплата за ресурсы |
| Cold start | 100-500 мс | 0 мс |
| Макс время выполнения | 15 мин | Без ограничений |
| Обслуживание инфры | Провайдер | Вы сами |
При нестабильной нагрузке serverless экономит до 5 раз по сравнению с VPS. Для постоянного трафика >1000 запросов/с VPS может быть дешевле.
Популярные плагины Serverless Framework
| Плагин | Назначение |
|---|---|
| serverless-esbuild | Быстрая сборка с tree shaking |
| serverless-offline | Локальная эмуляция Lambda и API Gateway |
| serverless-dotenv-plugin | Подгрузка .env-файлов |
| serverless-ssm-fetch | Автоматическое получение параметров из SSM |
CI/CD для Serverless Framework
Настройте GitHub Actions или GitLab CI для автоматического деплоя на разные стейджи. В workflow укажите шаги: checkout, установка зависимостей, деплой через npx serverless deploy --stage prod. Секреты храните в GitHub Secrets или GitLab CI Variables. Типичный pipeline dev → staging → prod занимает 2-3 минуты.
Что входит в настройку под ключ?
- Конфигурация
serverless.ymlс IAM, VPC, окружениями - Оптимизация сборки (esbuild, tree shaking, Lambda Layers)
- CI/CD (GitHub Actions / GitLab CI) для dev/staging/prod
- Управление секретами через SSM или Secrets Manager
- Документация с архитектурной схемой
- Обучение команды
- Поддержка после деплоя
Сроки
Базовая настройка с одной функцией и деплоем — 1 день. Полноценная инфраструктура с несколькими функциями, DynamoDB, SSM и CI/CD — 3–4 дня. Миграция с Express — 1–2 недели. Стоимость рассчитывается индивидуально в зависимости от сложности и объёма работ.
Свяжитесь с нами для аудита вашей serverless-архитектуры. Получите консультацию по настройке Serverless Framework — мы поможем избежать типичных ошибок и ускорить разработку.







