Quick Setup (prereq: npm
)
npm install -g serverless
Detailed Setup Instructions here
Basic project setup, test and deployment
A CRUD application with a dockerized environment to test AWS services locally. Python for services and DynamoDB for database.
Mono-repo style, i.e. service + IaaC
├──app/
├── __init__.py
├── create.py
├── delete.py
├── get.py
├── list.py
├── update.py
├── tests
│ ├── __init__.py
│ ├── conftest.py
│ └── test_create.py
└── utils
├── __init__.py
├── config.py
└── helpers.py
├──.env
├──Dockerfile
├──docker-compose.yml
├──requirements.txt
├──serverless.yml
app/
: Each CRUD function (create, retrieve/get, update, delete) is executed by AWS Lambda, and associated with an API endpoint.app/tests/
: Tests for Lambda handlers. Also includesconftest.py
forpytest
fixtures, that help in mocking or configuring your environment.app/utils/
: Helpers functionsserverless.yml
: Serverless configuration for the service (orapp
). Includes IaaC to generate AWS components (resources
), and attachfunctions
for Lambda handlers, among other things.docker-compose.yml
: includes- the default template from LocalStack, an open-source framework that mimics AWS enviroment closely on your local setup
- the build using
lambci
's Docker image to run and test the service locally.
docker-compose build
docker-compose up
NOTE: Build only if there's any change.
docker-compose run app pytest tests/ -s -vv
On the container for app
, all the tests located within the app/tests/
directory will run. This will also generate the AWS resources locally, via app/tests/conftest.py
(eg. ddb_tbl
fixture creates the DDB table serverless-workshop-rest-ddb-test
).
aws --endpoint-url=http://localhost:4566 ddb select serverless-workshop-rest-ddb-test
Querying locally to check if the table is created. Also, creates an entry from the test_create.py
test.
Optional Setup:
aws sso login --profile <profile-name>
yawsso
In order to deploy the endpoint simply run
serverless deploy --stage <dev/stg>
This converts your serverless.yml
config to a CloudFormation
stack, and packages your service and dependencies
The expected result should be similar to:
Serverless: Packaging service…
Serverless: Uploading CloudFormation file to S3…
Serverless: Uploading service .zip file to S3…
Serverless: Updating Stack…
Serverless: Checking Stack update progress…
Serverless: Stack update finished…
Service Information
service: serverless-rest-api-with-dynamodb
stage: dev
region: eu-central-1
api keys:
None
endpoints:
POST - https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos
GET - https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos
GET - https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/{id}
PUT - https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/{id}
DELETE - https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/{id}
functions:
serverless-rest-api-with-dynamodb-dev-update: arn:aws:lambda:eu-central-1:XXXXXXX:function:serverless-rest-api-with-dynamodb-dev-update
serverless-rest-api-with-dynamodb-dev-get: arn:aws:lambda:eu-central-1:XXXXXXX:function:serverless-rest-api-with-dynamodb-dev-get
serverless-rest-api-with-dynamodb-dev-list: arn:aws:lambda:eu-central-1:XXXXXXX:function:serverless-rest-api-with-dynamodb-dev-list
serverless-rest-api-with-dynamodb-dev-create: arn:aws:lambda:eu-central-1:XXXXXXX:function:serverless-rest-api-with-dynamodb-dev-create
serverless-rest-api-with-dynamodb-dev-delete: arn:aws:lambda:eu-central-1:XXXXXXX:function:serverless-rest-api-with-dynamodb-dev-delete
You can create, retrieve, update, or delete todos with the following commands:
via API Endpoints:
curl -X POST https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos --data '{ "text": "Learn Serverless" }'
No output
curl https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos
Example output:
[{"text":"Deploy my first service","id":"ac90feaa11e6-9ede-afdfa051af86","checked":true,"updatedAt":},{"text":"Learn Serverless","id":"206793aa11e6-9ede-afdfa051af86","createdAt":,"checked":false,"updatedAt":}]%
# Replace the <id> part with a real id from your todos table
curl https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/<id>
Example Result:
{"text":"Learn Serverless","id":"ee6490d0-aa11e6-9ede-afdfa051af86","createdAt":,"checked":false,"updatedAt":}%
# Replace the <id> part with a real id from your todos table
curl -X PUT https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/<id> --data '{ "text": "Learn Serverless", "checked": true }'
Example Result:
{"text":"Learn Serverless","id":"ee6490d0-aa11e6-9ede-afdfa051af86","createdAt":,"checked":true,"updatedAt":}%
# Replace the <id> part with a real id from your todos table
curl -X DELETE https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/<id>
via local CLI:
serverless invoke --function create --stage dev
No output
Don't forget to remove the app from your AWS environment. Here's a clean way to do it with serverless
serverless destroy --stage <dev/stg>
By default, AWS Lambda limits the total concurrent executions across all functions within a given region to 100. The default limit is a safety limit that protects you from costs due to potential runaway or recursive functions during initial development and testing. To increase this limit above the default, follow the steps in To request a limit increase for concurrent executions.
When you create a table, you specify how much provisioned throughput capacity you want to reserve for reads and writes. DynamoDB will reserve the necessary resources to meet your throughput needs while ensuring consistent, low-latency performance. You can change the provisioned throughput and increasing or decreasing capacity as needed.
This is can be done via settings in the serverless.yml
.
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
In case you expect a lot of traffic fluctuation we recommend to checkout this guide on how to auto scale DynamoDB https://aws.amazon.com/blogs/aws/auto-scale-dynamodb-with-dynamic-dynamodb/