Skip to content

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.

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
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
Email 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.app in the management/default AWS account.
  • Shared Dev zone: dev.vimmedicine.app delegated to the VIM Dev account.
  • Shared Stage zone: stage.vimmedicine.app delegated to the VIM Stage account.
  • Current/legacy Medplum dev zone: medplum-dev.vimmedicine.app delegated 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:

  1. CDK infrastructure config JSON — generated by npx medplum aws init; controls AWS resources.
  2. Runtime server config — stored in AWS SSM Parameter Store under /medplum/{env}/....
  3. 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

  1. Confirm AWS account, region, domain/subdomains, SES identity, access model, and owners.
  2. Configure AWS CLI credentials securely outside Slack.
  3. Run npx medplum aws init in the local CDK config repo.
  4. Review generated config and SSM parameters.
  5. Run CDK bootstrap/synth/diff.
  6. Review diff, IAM/security implications, and budget risk.
  7. Deploy infrastructure only after approval.
  8. Deploy Medplum app.
  9. Verify app, API, email, logs, RDS, Redis, WAF/CloudFront/ALB health.
  10. 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.app or future dev naming migrates to medplum.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.