Infrastructure
All infrastructure is AWS, defined in Terraform under deploy/ and applied per target: test in the old shared account (us-west-2), test in its own account (us-east-2, legacy tables in us-east-1), staging (us-east-2) and prod (us-east-2). Each target supplies the legacy-table region and the bucket the Lambda packages are uploaded to (legacy_region, artifact_bucket). Resource names carry the {env} prefix, except the shared us-east-1 tables, which have none; the application identifier is user-service. The {env}-user-service-users DynamoDB table and Kinesis stream are defined in the infrastructure repo (aws/user-service/) and consumed here as data sources. Terraform is applied by the {env}-github-services-deploy role from the infrastructure repo, which can only create IAM roles that carry the {env}-github-services-boundary permissions boundary; the Lambda module applies it by default and hand-written roles set permissions_boundary explicitly.
Lambda Functions
| Function | Trigger | Timeout | VPC | Key IAM Permissions |
|---|---|---|---|---|
|
API Gateway |
300s, 256 MB (512 MB in test) |
Private subnets, |
DynamoDB R/W on the users table + indexes, |
|
DynamoDB Streams on the users table ( |
840s |
Private subnets, |
|
|
SQS |
810s (90% of the queue visibility timeout) |
Private subnets, |
Invoke TXN and Entitlements; DynamoDB R/W on the users table and |
|
Kinesis |
840s |
Private subnets, |
Kinesis read; DynamoDB R/W on the users table, |
|
API Gateway (webhooks gateway, |
840s |
Private subnets, |
|
|
SQS |
840s |
none |
Invoke the user-service and Float gateways; Segment secret |
|
API Gateway (webhooks gateway, |
840s |
none |
|
|
Kinesis |
840s |
none |
Kinesis read; invoke the user-service gateway |
|
SQS |
27s (90% of the queue visibility timeout) |
none |
|
|
SQS |
30s |
none |
SQS receive/delete on |
Memory is the module default unless listed. Every Lambda runs the Datadog extension (ddlambda). VPC-attached Lambdas use the shared FloatMe VPC private subnets and PrivateSG security group; the lookups accept both the CFN-era tag names and the floatme-{env}-… names.
API Gateways
| Gateway | Routes | Notes |
|---|---|---|
|
|
30s integration timeout; access logs to |
|
|
Direct SQS integration, no Lambda; the JWT route forwards the |
SQS Queues
| Queue | Visibility Timeout | Max Receive | DLQ | Purpose |
|---|---|---|---|---|
|
900s |
5 |
Yes |
Janitor messages from the API (account closure, bans, data deletion) — Janitor |
|
900s |
5 |
Yes |
Typeform webhook payloads from the webhook-handler, consumed by the typeform Lambda |
|
30s |
5 |
Yes |
App metric events from the floatmetrics gateway and the |
|
180s |
1 |
Yes |
Access-code SMS requests from the API, consumed by the sms-worker — SMS delivery |
Each DLQ is named <queue>-dlq.
Kinesis
| Stream | Direction | Consumer configuration |
|---|---|---|
|
consumed |
payment-worker; filter |
|
consumed |
subscriptions Lambda; filter |
|
published |
Written by the kinesis-feeder; contracts in Events |
DynamoDB Tables
Schemas and access patterns are in DynamoDB Tables.
| Table | Region | Notes |
|---|---|---|
|
current region ( |
Single table, |
|
current region ( |
Settlement participants, |
|
current region |
App metric events, 2-day TTL |
|
us-east-1 in prod; current region in test |
Phone number per user, |
|
us-east-1 in prod; current region in test |
SMS access codes keyed by phone number |
|
us-east-1 in prod; current region in test |
Low-balance alert threshold per user |
The us-east-1 tables carry no environment prefix. Their client resolves the region from USR_LEGACY_DYNAMO_REGION (API) or LEGACY_DYNAMO_REGION (cleanup, subscriptions); the users table from USR_DYNAMO_REGION/USR_DYNAMO_TABLE or DYNAMO_REGION/DYNAMO_TABLE.
RDS
The API, subscriptions and cleanup Lambdas connect to the shared FloatMe PostgreSQL instance (ebdb database) through the {env}/rds/main (writes) and {env}/rds/replica (reads) secrets. Schema in PostgreSQL Schema.
EventBridge
| Rule | Routing |
|---|---|
|
Default bus → SQS |
The API Lambda holds events:PutEvents on the default bus and creates an event bus client named user-service.api; no code path publishes through it.
Secrets Manager
| Secret | Contents | Consumers |
|---|---|---|
|
RDS main credentials |
api, subscriptions |
|
RDS read-replica credentials |
api, subscriptions, cleanup |
|
Segment write key / access token |
api, subscriptions, cleanup, typeform |
|
Auth0 Management API credentials |
api, cleanup |
|
GrowthBook SDK key and host |
api, cleanup |
|
Castle API key |
api |
|
Iterable API key |
api, cleanup |
|
AppsFlyer S2S and API keys |
api, cleanup |
|
Zendesk agent email and API token |
api |
|
|
api |
|
Typeform webhook secret |
webhook-handler |
|
Tally webhook secret |
survey-webhook-handler |
|
Twilio |
sms-worker |
|
Datadog API and app keys |
Terraform (SLOs, service definition) |
The API exits at startup when the Fin secret is empty or when the Zendesk credentials are empty; the sms-worker exits when any Twilio field is empty.
Environment Configuration
Behaviour toggles and their per-environment values are catalogued in Feature Flags. Fixed integration parameters set by Terraform; staging takes the test value:
| Variable | test | prod | Effect |
|---|---|---|---|
|
|
|
Plaid IDV template passed to the Transactions Service |
|
|
|
Iterable message type the SMS opt-in endpoint subscribes users to |
|
|
|
AppsFlyer iOS app (Android |
|
Castle API |
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 SLOs, each 99.9% target / 99.99% warning over 7-day and 30-day windows:
-
Lambda Errors — api, kinesis-feeder, cleanup, subscriptions, webhook-handler, typeform, survey-webhook-handler
-
Lambda Throughput — kinesis-feeder, cleanup, webhook-handler, typeform, survey-webhook-handler
-
Lambda Latency — api, kinesis-feeder, cleanup, subscriptions, webhook-handler, typeform, survey-webhook-handler
The service definition (dd-service: user-service, tier 1, team devops) links to this repo and to https://docs.floatme.io/user-service.