Example project demonstrating how to take advantage of both Terraform & Terraform CDK (Typescript) to deploy graphql federated API's to a serverless environment (AWS Lambda).
The application code in this iteration is very MVP, as the intention was more of devops and infrastructure as code automation.
Primary Application Libraries:
Helpful Library Docs:
- @fastify/aws-lambda
- Mercurius Graphql Federation
- Mercurius Graphql Federation with NestJS
- GraphQL Code First Approach
Terraform specific project code
├── app
│ ├── admin
│ │ └── main.tf.ts
│ ├── gateway
│ │ └── main.tf.ts
│ └── products
│ └── main.tf.ts
├── infrastructure
│ └── dev
└── packages
└── cdktf-constructs
- This iteration is demonstrating storing state locally. So this does not demonstrate how to manage terraform state for a production environment. For that purpose I would highly recommend Terraform Cloud (a little biased) or other Terraform Backend options.
- Each application directory contains its own Terraform CDK Stack within:
main.tf.ts
. - They all resuse the same construct defined in the
@packages/cdktf-constructs
pnpm workspace package - The terraform packages have two levels in terms of sibling dependencies.
Infrastructure
is required to be deployed prior to any other package since it contains the S3 bucket for lambda deployment artifacts.- Both
products
&admin
packages need to be deployed prior to thegateway
package. For service discovery, the gateway needs to aware of each subgraph in order to stitch schema requests. Managed services like Apollo Studio or self managed isolated microservice to manage that is preferred in a production environment. - The dependency order of package deployments is handled by TurboRepo pipelines
- As mentioned previously, since state is stored locally, each package references other terraform stacks output(s) via the
DataTerraformRemoteStateLocal
construct
-
Install pnpm
@latest
or@^7.5.2
npm install -g pnpm@latest
-
Install dependencies with:
pnpm install
-
Turborepo is included as a dev dependency in the workspace root directory
- Setup your access key & secret access for AWS
- If not exported in your environment shell can do the following:
- Add .env.local to each app/[package] directory
AWS_ACCESS_KEY_ID='' AWS_SECRET_ACCESS_KEY=''
- Within
infrastructure/
copy auto.tfvars.example toauto.tfvars
and add your credentials there
- Add .env.local to each app/[package] directory
- If not exported in your environment shell can do the following:
- Then Deploy!
pnpm run deploy:turbo
- Once finished, remember to destory the resources you created by:
if it fails, can run
pnpm run destroy:turbo
pnpm run destroy:infrastructure
&turbo run destroy
separately
- I would consolidate Terraform CDK Stacks into a single application to deploy from. Terraform cdktf deploy command allows the user to specify a particular stack to deploy.
- Since this iteration uses local state, would recommend persisting terraform state remotely with Terraform Cloud, S3, or other Terraform Backend solutions
- I would also update the gateway application code to fetch the other subgraph api gateway endpoint urls at runtime (with caching). That way each subgraph and package can be deployed independently, without the need of re-deploying the gateway to update an environment variable.
- Research adding another useful library to compliment NestJS Nestjs-query