This repository contains a Books API powered by Amazon API Gateway, AWS Lambda and Amazon DynamoDB. Resources are defined and provisioned using AWS SAM.
For CI/CD it assumes there are two environments: staging and production. Pipeline is implemented using AWS CDK.
Table of contents:
Application is an RESTful API around the book resource. It currently supports an endpoint for registering new books and another one for retrieving them. This API is implemented using Amazon API Gateway and AWS Lambda where authentication is provided by Amazon Cognito. Amazon DynamoDB is the chosen data store.

aws configure to set up your terminal.Use the repository .nvmrc to select the expected Node.js version:
nvm use
node --version
npm --version
aws-serverless-books-api-sample
|- events // HTTP request samples to test the app locally using sam local
|- images // images for this README
|- pipeline // CDK app defining a CI/CD pipeline for the API
|- src // source code
|- template.yml
AWS SAM template is defined in the root directory through a YAML file. It defines:
Parameter that specifies to which environment we are going to be deploying to.Condition that based on the parameter above determines if this is a deployment to production or not. This is needed as different resources and configurations will be used based on the environment.Global section to define those parameters that are common to multiple resources in the template.Books API that glues together the configuration for our API including monitoring, tracing or authorization methods.CreateBook which is responsible for grabbing book attributes from the HTTP request and storing them into a DynamoDB table. Configuration:GetAllBooks function peforms a scan over the book table and return all results back to the client. Considerations:DynamoDBReadPolicy.AliasErrorMetricGreaterThanZeroAlarm) that monitors if the new version of the function throws errors, performing a rollback in case it does.CreateBookPreTraffic). If it fails, traffic is not routed to the new version and deployment is considered failed.Metadata section for each function.@aws-sdk/client-dynamodb, rather than relying on a Lambda-bundled AWS SDK.Books.CognitoUserPool. In order to get a token, we need to define a client and domain (instructions to manually get a token using Postman are explained below). Aformentioned client only supports the OAuth implicit grant.aws.cognito.signin.user.admin scope (only scope that can be obtained when generating an access token through Cognito SDK).Packaging and deploying the app to AWS is relatively straight forward since all configuration is defined in template.yml.
sh
npm install -g esbuild
sam build
template.yml pointing to where your artifacts have been stored in S3.sh
sam package --s3-bucket my-artifacts-bucket --s3-prefix my-prefix --output-template-file out.yml
sh
sam deploy --template-file out.yml --stack-name my-stack-staging --parameter-overrides ParameterKey=Stage,ParameterValue=staging --capabilities CAPABILITY_IAM
You can monitor how the deployment is happening through AWS CodeDeploy as the above will create a new application in this service alongside a deployment group for your function.
These three commands will be used in both Build and Deploy steps of our pipeline.
AWS SAM Accelerate provides a faster development experience by automatically syncing your local changes to the cloud. This is particularly useful during development as it eliminates the need to run the full build-package-deploy cycle for every code change you want to try out.
sh
sam sync --stack-name <my-dev-stack>
sh
sam sync --stack-name <my-dev-stack> --code --resource-id CreateBook
sh
sam sync --stack-name <my-dev-stack> --watch
sh
sam sync --stack-name my-stack-dev --watch --code --resource-id GetAllBooks
The watch mode is particularly useful during active development as it detects file changes and automatically syncs them to AWS without requiring manual intervention. This significantly speeds up the development cycle compared to traditional deployment methods.
Note that sam sync is intended for development purposes only and not recommended for production deployments. For production, use CI/CD pipelines.
Run a local DynamoDB container:
docker run -d -p 8000:8000 --name dynamodb amazon/dynamodb-local -jar DynamoDBLocal.jar -sharedDb
Create the following table in the local DynamoDB:
aws dynamodb create-table --table-name books \
--attribute-definitions AttributeName=isbn,AttributeType=S \
--key-schema AttributeName=isbn,KeyType=HASH \
--endpoint-url http://localhost:8000 \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5
Check previous step ran successfully:
aws dynamodb list-tables --endpoint-url http://localhost:8000
aws dynamodb describe-table --table-name books --endpoint-url http://localhost:8000
Finally, test your function with a dummy event (that can be generated with sam local generate-event sqs receive-message):
docker network create my-network
docker network connect my-network dynamodb
sam local invoke CreateBook -e events/create-book-request.json --env-vars events/env.json --debug-port 5858 --docker-network my-network
sam local invoke GetAllBooks -e events/get-all-books-request.json --env-vars events/env.json --debug-port 5858 --docker-network my-network
Notice that our lambda functions will point to the local DynamoDB container for the command above through its HTTP layer. Condition is based on AWS_SAM_LOCAL which automatically gets set by sam when executing local commands. Similarly, integration with AWS X-Ray is only performed outside local environment.
A very similar approach using Docker will be taken to perform end-to-end tests for our Lambda function and its integration with DynamoDB.
If Docker is unavailable locally and you use Finch, use equivalent Finch commands for local validation. Keep CodeBuild scripts using Docker commands because Docker is available in CodeBuild standard images.
Run package-level checks from each package directory:
cd src/books/create && npm ci && npm test && npm run build && npm audit
cd ../get-all && npm ci && npm test && npm run build && npm audit
cd ../create-pre-traffic && npm ci && npm run build && npm audit
cd ../tests && npm ci && npm test && npm audit
Run SAM and CDK checks from the repository root and pipeline package:
sam validate
sam build
cd pipeline
npm ci
npm run build
cdk synth
AWS SAM CLI allows to monitor any Lambda function given its logical id within a stack or its name as we would visualize them using Cloudwatch. For ie:
sam logs -n CreateBook --stack-name BooksApiStaging --tail
Once we start interacting with the API through the two available endpoints, traces will be stored in AWS X-Ray since TracingEnabled was set to true in the definition of BooksApi in template.yml.
By navigating through the AWS console to AWS X-Ray, we can load the service map of our API and look for application issues, bottlenecks or specific areas that need improving.

Source -> Build -> Staging (Deploy + Test) -> Production (Manual approval + Deploy)
Stages and actions are implemented using AWS CodePipeline, AWS CodeBuild and AWS CodeDeploy (behind the scenes through sam deploy command).
Pipeline itself is defined and provisioned by AWS CDK using Typescript.
To get it provisioned follow these steps:
sh
aws ssm put-parameter --name github_connection_arn --value <YOUR_GITHUB_CONNECTION_ARN>
sh
npm install -g aws-cdk
```sh cd pipeline npm i
# bootstrap cdk for the target accont and region export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text) export AWS_REGION=$(aws configure get region)
cdk bootstrap aws://$ACCOUNT_ID/$AWS_REGION
npm run build cdk deploy ```
There will be a summary of security-related changes that needs to be approved to continue with the CloudFormation stack creation.
NOTES:
gitRepo, gitOwner and gitBranch on pipeline/lib/pipeline_stack.ts to point to your Github repository.ci-cd-pipeline-artifacts-{accountId}-{region}.books-api-artifacts-{accountId}-{region}.Build stage doesn't only generate API artifacts, it also run a suite of unit tests for our AWS Lambda functions.

Once the application is deployed in staging, end-to-end tests are executed automatically. These tests interact directly with the provisioned app. Certain parameters such as the API endpoint or DynamoDB table name are made available to this action through CloudFormation Outputs.

Any user that wants to create books using the API directly, needs an OAuth2 token that grants ac
$ claude mcp add aws-serverless-books-api-sample \
-- python -m otcore.mcp_server <graph>