Infrastructure
Physical AWS resources, as provisioned by deploy/ in this repo. The DynamoDB table itself is
provisioned in the infrastructure repo (aws/underwriting/); this stack only reads it as a
data source. The continuous environments are test in the old shared account (us-west-2),
test in its own account (us-east-2) and staging (us-east-2, its own account), all deployed
on push to main; prod (us-east-2) deploys on release publish. The SageMaker models only
exist in the old test account and prod (sagemaker_enabled).
Deployment
on_pr.yaml, on_main.yaml and on_release.yaml each call deploy-env.yaml once per target,
passing the account, region, state bucket, artifact bucket and sagemaker_enabled as inputs.
A pull request builds once and plans every continuous target from that build with the read-only
site-github-services-plan role; a push to main applies the same build to each with
site-github-services-deploy; a published release applies prod from the release’s tarball.
Authentication is GitHub OIDC with no static credentials. Both roles, and the
site-github-services-boundary permissions boundary fmtf-module-lambda attaches to every
function role, are owned by the infrastructure repo. The Terraform providers use the workflow’s
credentials directly, with no further role assumption. State lives under
terraform/underwriting-api/ in floatme-site-media for old test and prod and in
floatme-site-services-terraform-state for the new test account and staging, locked by the
terraform-locking table in each account. Lambda packages upload to the bucket named by
artifact_bucket: floatme-site-media except in the new test account, where it is
floatme-test-services-artifacts.
The seven peer service APIs are resolved by name at plan time and addressed by convention
(https://{id}.execute-api.{region}.amazonaws.com). A peer that has not yet deployed to an
environment yields an empty URL and an account-wide execute-api:Invoke grant until the next
deploy picks up its id, so a fresh environment comes up in two passes rather than failing the
plan.
Lambda functions
All five are built from cmd/<name>/main.go, named site-underwriting-<name>, and deployed
via the shared fmtf-module-lambda module. Memory is 256 MB in prod, 128 MB elsewhere.
| Function | Timeout | VPC | Trigger | Notable configuration |
|---|---|---|---|---|
|
300s |
yes |
API Gateway ( |
URLs/regions for all seven peer services; |
|
108s |
no |
|
Peer service URLs; |
|
108s |
no |
|
|
|
108s |
no |
|
Dynamo + transactions/user service + EventBridge region; |
|
108s |
no |
|
Dynamo only ( |
Source: deploy/lambda.tf, deploy/main.tf
IAM per function
| Function | Permissions |
|---|---|
|
DynamoDB (BatchGet/BatchWrite/Get/Put/Query) on table+indexes; |
|
DynamoDB (adds UpdateItem); SQS receive on its tap; |
|
DynamoDB (incl. UpdateItem); SQS receive on its tap; |
|
DynamoDB (incl. UpdateItem); SQS receive on its tap; |
|
DynamoDB (BatchGet/Get/Put/Query); SQS receive on its tap |
Source: deploy/lambda.tf
API Gateway
HTTP API (v2) named site-underwriting, single route ANY /{proxy+} with AWS_IAM
authorization, AWS_PROXY integration to the api Lambda (payload format 1.0, 30s timeout). The
public /v1 prefix is mapped outside this repo. Access logs go to
API-Gateway-Execution-Logs_underwriting/site with 7-day retention.
The gateway is also reachable as underwriting.site.svc.floatme.io (deploy/domain.tf): an
alias record in the infrastructure repo’s per-environment site.svc.floatme.io zone, using
its wildcard certificate. The domain, mapping, and record are standalone resources rather than
module inputs because the module disables the execute-api endpoint for HTTP APIs when it creates
a domain; that endpoint stays enabled for existing callers.
Source: deploy/lambda.tf, deploy/domain.tf
SQS queues
Four tap queues, each fed by one EventBridge rule (patterns in
Events) and consumed by one Lambda. All main queues: visibility
timeout 120s, maxReceiveCount 1 → DLQ. Retention is the AWS default (4 days) on both mains
and DLQs.
| Queue | DLQ |
|---|---|
|
|
|
|
|
|
|
|
Source: deploy/sqs.tf, deploy/main.tf
DynamoDB table
site-underwriting — single table, keys PK/SK, TTL attribute ttl, GSI1 and GSI2 (both
KEYS_ONLY projection). Prod is provisioned capacity with autoscaling; other environments are
on-demand. Point-in-time recovery and deletion protection are enabled. Key design and access
patterns: DynamoDB.
Source: infrastructure repo, aws/underwriting/dynamo.tf
Secrets
| Secret | Env var | Used by |
|---|---|---|
|
|
api, rule-runner, result-runner (feature flags) |
|
|
rule-runner, result-runner, float-created-handler (analytics events) |
|
|
result-runner (early-advance notification) |
|
— |
Terraform Datadog provider only |
Source: deploy/secrets.tf, deploy/lambda.tf
SageMaker
The sagemaker_enabled Terraform variable (default true; the staging deploy sets it false)
says whether the machine-learning repo’s models exist in the environment. When false, the
feature-store KMS alias is not looked up, the SageMaker and KMS IAM statements are left off the
api and rule-runner roles, and both functions are told not to call the models:
SAGEMAKER_ENABLED=false makes the rule runner skip the rule-ML call
(Rules Reference) and PAYBACK_PREDICTOR_ENABLED=false
makes the API run without the payback predictor
(Payback Predictor V2). The endpoint and feature
group names are still set but unused.
Source: deploy/variables.tf, deploy/lambda.tf, deploy/main.tf, cmd/api/main.go
Monitoring
Datadog monitors and SLOs exist in prod only (local.create_datadog_monitors in deploy/datadog.tf). Alerts outside prod go unread, and the old and new test accounts both deploy as test, so Datadog would reject the second account’s identical monitors as duplicates.
Datadog monitors are created inside the shared Lambda module; this stack aggregates them into
three SLOs (errors, throughput, latency), each targeting 99.9% over 7d/30d and covering api,
rule-runner, result-runner, and profile-handler (float-created-handler is not in any
SLO). A Datadog service definition registers the service as underwriting, tier 1.
Source: deploy/datadog.tf
Referenced (not provisioned here)
EventBridge default bus; the seven peer service API Gateways (txn, floats, insight,
user-service, subscription-service, payments, loc-service); and, where SageMaker is
enabled, the endpoints underwriting-inference-endpoint-site (rule ML) and
underwriting-v2-inference-endpoint-site (payback predictor v2) and the feature group
site-machine-learning-underwriting-v2-user-features with its KMS key (owned by the
machine-learning repo).