Infrastructure
This page documents the AWS infrastructure provisioned by Terraform for the qa-automation service.
All resources are defined in the deploy/ directory and are applied via GitHub Actions to each environment in the table below.
Every environment-specific name is derived from var.environment (test today, staging next), so the same configuration deploys to any non-production environment.
The infrastructure is managed using the fmtf-module-lambda internal module and the terraform-aws-modules/apigateway-v2 community module.
| This service is deployed only to non-production environments and is never deployed to production. |
Names below are shown for the test environment; substitute the environment prefix (test-, staging-, test/, staging/) elsewhere.
This service names its own API gateway qa.<env>.svc.floatme.io under the per-environment zone infra provides, so callers can address it without knowing its API ID. Peers will get the same treatment as each adopts a name; until then their URLs are resolved as described next.
Resources owned by other services are not looked up at plan time. Peer API gateways resolve to an empty URL when absent, and queues and job Lambdas are addressed by name convention, so this service can be planned and applied in a fresh environment before its peers exist. A second deploy fills in the API URLs once every peer has deployed. Infra-owned resources (DynamoDB tables, the Kinesis stream, secrets, VPC) are looked up and must exist first.
Deployment
GitHub Actions authenticates to AWS with OIDC, never static keys: pull requests plan with the read-only <env>-github-services-plan role, and pushes to main apply with <env>-github-services-deploy.
Both roles, the permissions boundary the Lambda role carries, and the state bucket are created by floatme-corp/infrastructure (modules/github-services-ci).
The apply workflow also accepts workflow_dispatch; re-running it is the second pass a fresh environment needs to resolve peer API URLs that did not exist on the first.
| Environment | AWS account | Region | Terraform state bucket | Lambda artifact bucket |
|---|---|---|---|---|
|
|
us-west-2 |
|
|
|
|
us-east-2 |
|
|
|
|
us-east-2 |
|
|
The state key is terraform/qa/terraform.tfstate and the lock table terraform-locking in every environment.
The two test targets share an environment name, so every per-target value is a deploy-env.yaml input: the artifact bucket is var.artifact_bucket (the fmtf-module-lambda default is the old account’s bucket, whose name is taken) and the Dynamo regions are var.dynamo_region and var.dynamo_legacy_region.
deploy/.terraform.lock.hcl is committed so the provider plugin cache the devkit mounts at /cache is used and provider upgrades go through review.
Every AWS provider applies the organization’s cost-allocation tags as default tags, matching floatme-corp/infrastructure: floatme:environment (var.environment), floatme:application (qa), floatme:managed-by (terraform), and floatme:repository (floatme-corp/qa-automation).
The org tag policy enumerates these keys and the allowed environment values; resource-level tags only add a name.
Lambda Functions
One Lambda function is deployed.
It is built from the cmd/api entrypoint, packaged as a binary in dist/, and deployed using the internal fmtf-module-lambda module (v2.1.0), which also attaches the environment’s <env>-github-services-boundary permissions boundary to the function’s IAM role.
| Function | Trigger | Timeout | Memory | Key IAM Permissions |
|---|---|---|---|---|
|
API Gateway HTTP API (AWS IAM SigV4) — |
300s |
Module default |
|
Environment Variables
The Lambda receives the following runtime configuration via environment variables:
| Variable | Value / Source |
|---|---|
|
|
|
Hardcoded at deploy time |
|
Hardcoded at deploy time |
|
Hardcoded at deploy time |
|
|
|
|
|
|
|
|
|
Resolved from |
|
Resolved from |
|
Resolved from |
|
Resolved from |
|
Resolved from |
|
Resolved from |
|
Resolved from |
|
Resolved from |
|
Resolved from |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
API Gateway
The HTTP API (API Gateway v2) is provisioned using the terraform-aws-modules/apigateway-v2 module (v6.1.0).
| Property | Value |
|---|---|
Name |
|
Protocol |
HTTP API (API Gateway v2) |
Custom domain |
|
Endpoint URL |
The custom domain above; the auto-assigned |
Auth type |
|
Integration payload format |
|
Integration timeout |
30,000 ms (30s) |
DynamoDB Tables
The Lambda reads and writes to five DynamoDB tables.
The environment-prefixed table lives in var.dynamo_region (us-west-2 in the old test account, us-east-2 in the new one and staging).
The unprefixed FloatMeAPI-era tables live in var.dynamo_legacy_region (us-west-2 in the old test account, us-east-1 in the new one, staging and prod, mirroring where prod keeps them), reached through the aws.legacy_dynamo provider at deploy time and DYNAMO_LEGACY_REGION at runtime.
These tables are pre-existing (looked up via data sources) and are not created by this service.
| Table | Region | Purpose |
|---|---|---|
|
|
Stores requirement bypass rules used by test flows to skip eligibility checks (e.g., advance eligibility, KYC gates) |
|
|
Subscription billing activity records (current); read and written during subscription lifecycle tests |
|
|
Historical billing activity; queried during subscription history assertions in tests |
|
|
Underwriting decision records used during underwriting flow tests |
|
|
Float collection-attempt log (owned by float-service); seeded so a test user can be given a collection history the collections and underwriting flows read back as real — e.g. the |
Secrets Manager
All secrets are stored in AWS Secrets Manager under the test/ path prefix and are referenced by name in the Lambda’s environment.
The Lambda retrieves them at startup via secretsmanager:GetSecretValue.
| Secret name (path) | Environment variable | Contents |
|---|---|---|
|
|
Auth0 credentials — client ID, client secret, and domain used to obtain tokens for test user authentication flows |
|
|
Primary RDS database credentials — host, port, username, and password for direct DB access during test setup and teardown |
|
|
Plaid API credentials — client ID and secret for simulating bank link and transaction flows in the test environment |
|
|
GrowthBook SDK key and API credentials used to read and override feature flag state during tests |
|
|
Iterable server-side API key for verifying email and push notification events triggered by test flows |
|
|
Iterable mobile (JWT) API key used to authenticate mobile-originated notification events in tests |
|
(Terraform only — not injected into Lambda) |
Datadog |
VPC
The Lambda runs inside the FloatMe VPC for its target (us-west-2 in the old test account, us-east-2 in the new one and staging).
Subnet and security group resources are looked up by tag name at deploy time rather than hardcoded by ID.
| Resource | Details |
|---|---|
Private Subnet 1 |
Tagged |
Private Subnet 2 |
Tagged |
Security Group |
Tagged |
Placing the Lambda in private subnets ensures it can reach RDS and other internal services over the VPC network without exposing them to the public internet.
Datadog
No Datadog monitors or SLOs are provisioned for this service.
The fmtf-module-lambda per-function monitors (error rate, throughput, latency) are disabled on the api module call: nobody acts on them for QA tooling, and the old and new test accounts both deploy under the test environment name, so identical monitors from the two accounts would be rejected by Datadog as duplicates.
A Datadog service definition (schema v2.2) is registered for the qa service, linking it to:
-
Tier: 1
-
Team: devops
-
Support channel:
#CMWE5RX8Bon Slack -
Source repository: https://github.com/floatme-corp/qa-automation
Datadog credentials (api_key, app_key) are sourced from test/datadog/terraform in Secrets Manager and are used only by the Terraform provider — they are not injected into the Lambda runtime.