Medplum Architecture & Configuration Brief¶
Last updated: 2026-05-31T13:06:58Z
Executive summary¶
VIM is deploying Medplum first, but the AWS environment model is not Medplum-specific. Dev, Stage, and Prod are shared VIM environment accounts that will host Medplum, the Patient app, Doctor UI, and other future services.
Medplum should still be treated as regulated healthcare infrastructure even in dev. The working rule remains: synthetic data only; no PHI; no production credentials; no production integrations until engineering, security/compliance, and clinical review are complete.
Confirmed environment/account model¶
| Environment | AWS account | AWS profile | Purpose |
|---|---|---|---|
| Dev | 342624924188 |
vim-dev / legacy vim-medplum-dev |
Shared dev for all apps |
| Stage | 349348221665 |
vim-stage |
Shared production rehearsal / release validation |
| Prod | 310858751630 |
vim-prod |
Shared production workloads |
Important naming principle: do not rename accounts, repos, or DNS around Medplum as if the environments are Medplum-only. Keep shared environment concepts (vim-dev, vim-stage, vim-prod, dev.vimmedicine.app, stage.vimmedicine.app) and treat Medplum as one workload inside them.
Recommended initial architecture¶
VIM users
-> Route 53 DNS / ACM certificates
-> App domain: CloudFront + S3 static Medplum app
-> API domain: WAF/ALB + ECS/Fargate Medplum server
-> Storage domain: CloudFront + S3 storage bucket
Medplum server dependencies:
-> Aurora/RDS Postgres
-> ElastiCache Redis
-> AWS Secrets Manager
-> AWS SSM Parameter Store
-> SES for system email
-> CloudWatch logs/metrics
Recommended VIM defaults¶
| Decision | Recommendation |
|---|---|
| Account model | Shared VIM environment accounts: Dev, Stage, Prod |
| Region | us-east-1 unless VIM has a standard region policy |
| Environment names | dev, stage, prod |
| Parent/internal domain | vimmedicine.app |
| Shared non-prod zones | dev.vimmedicine.app, stage.vimmedicine.app |
| Medplum dev current/legacy DNS | api/app/storage.medplum-dev.vimmedicine.app |
| Medplum future non-prod DNS | api/app/storage.medplum.dev.vimmedicine.app, api/app/storage.medplum.stage.vimmedicine.app |
| Medplum prod internal DNS | Delegate medplum.vimmedicine.app to Prod when prod Medplum is imminent |
| Access model | IP-allowlisted/WAF/VPN if practical; otherwise public dev endpoints protected by WAF and synthetic-only policy |
SES sender identity per environment, e.g. no-reply@medplum.vimmedicine.app for prod Medplum |
|
| Data policy | Synthetic-only until formal review |
| Observability | CloudWatch logs/metrics/alarms for dev baseline; production observability decision later |
| Budget | Budget alarm required before deploy |
DNS setup and direction¶
Configured/confirmed in the architecture thread:
- Parent hosted zone:
vimmedicine.appin the management/default AWS account. - Shared Dev zone:
dev.vimmedicine.appdelegated to the VIM Dev account. - Shared Stage zone:
stage.vimmedicine.appdelegated to the VIM Stage account. - Current/legacy Medplum dev zone:
medplum-dev.vimmedicine.appdelegated to the VIM Dev account (342624924188).
Production internal Medplum should use an app-specific zone delegated to Prod as needed:
medplum.vimmedicine.app -> VIM Prod account
Then Medplum prod can use:
api.medplum.vimmedicine.app
app.medplum.vimmedicine.app
storage.medplum.vimmedicine.app
Rationale for app-specific prod delegation: keep the management account as parent-domain owner, keep Prod as production workload owner, limit DNS permissions/blast radius, and avoid Medplum CDK cross-account Route 53 complexity.
Configuration model¶
Medplum AWS deployments have three main configuration layers:
- CDK infrastructure config JSON — generated by
npx medplum aws init; controls AWS resources. - Runtime server config — stored in AWS SSM Parameter Store under
/medplum/{env}/.... - Secrets — stored in AWS Secrets Manager or generated AWS resources; never stored in Slack, markdown docs, or git.
Key CDK config areas to review before deploy:
- Account, region, stack name, environment name.
- App/API/storage domains and ACM certificate ARNs.
- Storage bucket name and CloudFront signing public key.
- API exposure: public/private, WAF/IP allowlist.
- Database and Redis sizing.
- Fargate server image, CPU, memory, desired count.
- Load balancer logging, ClamAV scanning, and autoscaling.
Deployment phases¶
- Confirm AWS account, region, domain/subdomains, SES identity, access model, and owners.
- Configure AWS CLI credentials securely outside Slack.
- Run
npx medplum aws initin the local CDK config repo. - Review generated config and SSM parameters.
- Run CDK bootstrap/synth/diff.
- Review diff, IAM/security implications, and budget risk.
- Deploy infrastructure only after approval.
- Deploy Medplum app.
- Verify app, API, email, logs, RDS, Redis, WAF/CloudFront/ALB health.
- Update runbooks and decision/risk logs.
Current blocker / next decisions¶
Before the next environment deploy, VIM should confirm:
- Whether current dev stays on
medplum-dev.vimmedicine.appor future dev naming migrates tomedplum.dev.vimmedicine.app. - SES sender identity per environment.
- Access model per environment: public + WAF, IP allowlist, VPN/private, or another model.
- Budget alarm threshold and owner for Dev, Stage, and Prod.
- Security/compliance reviewer.
- Clinical reviewer before any real-data use.
Next decision for Jeremy¶
Confirm the naming/access/SES/budget items above. After that, the next technical steps are environment-specific preflight, npx medplum aws init, CDK bootstrap/synth/diff, human review, and deployment.