Deploy your FastAPI app on AWS API Gateway REST using Terraform + OpenAPI.
Includes hosted Swagger UI on S3 with custom domains and versioning.
This boilerplate lets you deploy versioned FastAPI applications on AWS API Gateway (REST) with:
- OAuth2 & API Keys
- Throttling & burst limits
- Response caching
- Custom domain names
- Hosted Swagger UI for each version
It automatically transforms the default OpenAPI schema from FastAPI by injecting AWS-specific extensions β no manual editing needed.
- π Auth & Usage Plans β OAuth2, API Keys, Usage Plans
- π¦ Traffic Control β Throttling and burst settings
- β‘ Response Caching β Low latency, faster APIs
- π Multi-Version Docs β Swagger UI hosted per version (on S3)
- π Custom Domains β Subdomain config per environment
Install:
make helpAll commands follow this format: make <command>-<stage>
In this tutorial, the dev environment is used.
Example: make deploy-dev
uv venv .venv
uv syncyarnEdit config.py:
"aws_region": "eu-west-3",
"aws_accounts": {
"dev": {
"aws_account": "408566731358", # Your aws accound ID
"profile": "fast-rest-api", # The aws profile you set for this account in your .aws/credentials file.
"live": False # Wheter or not it is your production environment
},
}Later on, you will be able to declare multiple stages (dev, staging, prod, etc.). The "live" parameter is primarily used for configuring custom domain names.
For non-live environments, such as dev, the stage name is included in the URLs:
Stage API URL Docs URL dev api.dev.fastawsrestpi.comdoc.api.dev.fastawsrestpi.comprod (live) api.fastawsrestpi.comdoc.api.fastawsrestpi.com
make tf-init-devThis command downloads the AWS providers and the necessary modules into the
.infra/.terraformdirectory.It also creates a local directory
.infra/terraform/terraform.tfstate.d/devwhere the Terraform state will be stored. However, you can use any Terraform backend to store your Terraform state, such as S3 or Terraform Cloud. This can be specified in theversion.tffile.
make tf-apply-ecr-devBefore building and pushing the Docker image for the Lambda function, it is necessary to create an ECR repository to store the Lambda image. Execute the command
make tf-ecr-devto apply the Terraform configuration specifically for theaws_ecr_repositoryresources defined in the.infra/terraform/ecr.tffile.
make build-push-lambda-image-devThis command builds your Docker image using the specified Dockerfile.
You can find the original example here.
Note that an
aws_ecr_lifecycle_policyis in place, which is useful for automatically removing untagged images.The API source code is located in the
src/api/directory. For each version of your API, a subfolder exists insrc/api/versions. In the initial version of this boilerplate, only two versions exists: v1 and v2.In theses folder you will find an app.py where a lambda handler (entrypoint for the lambdas) can be found. This entrypoint is used in
.infra/terraform/api.tffolder.
make generate-openapi-files-devUse the command
make generate-openapi-files-devto generate the OpenAPI files for each version of your API. Two files are created for each version:
openapi-<version>-terraform.json: This file contains all routes, including those that are hidden. It also includes anx-amazon-apigateway-integrationconfiguration for each route and adds an OPTIONS route for every path to support CORS in the documentation. Additionally, it sets the security schema for Oauth2Credentials with the correct format for Cognito user pool authorization.openapi-<version>-swagger.json: This file is the default file generated by FastAPI. Hidden routes are not visible, and it will be used for documentation purposes.
make tf-apply-devThis command apply the terraform configuration. It will deployed the following infrastructure.
make upload-openapi-files-to-s3-dev
This command inserts the URL of the previously created API into the
serverskey of theopenapi-*-swagger.jsonfiles. It then uploads these files to the previously created S3 bucket.
make build-swagger-ui-dev
This command builds the swagger documenation
make publish-doc-dev
This command upload push it to the previously created s3 bucket. The link of your api documentation should appear in the terminal
Screen.Recording.2025-05-03.at.19.18.40.mov
First make sure you have access to the dns record of your domain name.
Then in the config.py set the use_custom_domain_name to true and set domain_name to your domain name.
"networking": {
"domain_name": "fastawsrestapi.com", # Set your domain name here
"use_custom_domain": True, # Set this field to True
},You can execute the
make tf-apply-devcommand, but be prepared for it to initially fail. This is because it attempts to create a certificate for the custom domain name.For Amazon to verify domain ownership, you must add a temporary CNAME record to your DNS settings.
As mentioned earlier, you need to prove to AWS that you own the domain name.Select the N. Virginia (us-east-1) region in your AWS account. Even if you specified a different
aws_regionin the config.py, certificates for EDGE APIs and CloudFront distributions must be created in the us-east-1 region.Then, navigate to the AWS Certificate Manager service, where you should see an ACM certificate registered for the domain name
api.dev.yourdomainname.com, pending validation.
To validate, click on the certificate ID and retrieve the CNAME name and CNAME value.
Go to your domain name provider's settings (such as Ionos, GoDaddy, Gandi, Route53, etc.) and register a new CNAME record with these values.
In this demonstration, we provide an example using Route53. Navigate to the hosted zone.
Click on "Create a new record" and choose the simple routing policy.Next, click on "Define simple record."
Select the CNAME record type and enter the CNAME record value from the ACM certificate manager.
β οΈ Depending on your domain provider, you may need to trim the end of the CNAME name.Example: _36acjkmlkfesslea0b889e4b4cfc96cdb91.api.dev.fastawsrestapi.com. => _36acjkmlkfesslea0b889e4b4cfc96cdb91.api.dev
Then click on "Define simple record" and then "Create records."
You will need to wait for the DNS to propagate. Once complete, the status of your certificate should change from "Pending validation" to "Validated." This process typically takes about 5 minutes, but it can sometimes take longer.
Once your certificate is validated, its status should appear as "Issued."
You can rerun the `make tf-apply-dev` command. (If it fails, you might want to retry it once.)After this, you should create a CNAME between the AWS custom domain name that has been created.
To do this, go to the API Gateway service (ensure you select the region specified in the config.py) and click on "Custom domain names." Your newly created domain name should appear as follows:
Return to your domain provider's DNS Records and create a new CNAME record.
The CNAME Name should be
api.devand the CNAME value should be the API Gateway domain name found on your custom domain name page info.Wait for the CNAME to propagate. You can use the tool https://dnschecker.org/#CNAME/ to check if the DNS propagation is complete (in my exemple I check for api.dev.fastawsrestapi.com)
Now that you have registered this new domain name, you want it to appear and be used in your documentation.
To do this, you can run the command
make doc(it launches under the hoodmake generate-openapi-files-dev, make upload-openapi-files-to-s3-dev, make build-swagger-ui-dev, and make publish-doc-dev).When
make generate-openapi-files-devis launched, it checks the environment variableUSE_CUSTOM_DOMAIN. If it is true, it injects the custom domain name into the servers section of your OpenAPI files.










