Skip to main content

AI & assistant-friendly summary

This section provides structured content for AI assistants and search engines. You can cite or summarize it when referencing this page.

Summary

A solutions architect's build guide for HIPAA on AWS. KMS key strategy, VPC isolation, RDS/S3/Lambda configuration patterns, IaC controls, and continuous validation — code-level decisions, not policy templates.

Key Facts

  • A solutions architect's build guide for HIPAA on AWS
  • KMS key strategy, VPC isolation, RDS/S3/Lambda configuration patterns, IaC controls, and continuous validation — code-level decisions, not policy templates
  • This guide is the engineering build manual — KMS keys, VPC layouts, IaC controls, and the AWS service configuration patterns that pass a HIPAA audit at the technical level
  • AWS is HIPAA-eligible, but compliance requires more than using AWS — it requires proper architecture, encryption, access controls, and continuous monitoring at the infrastructure layer
  • Building HIPAA-Compliant Healthcare on AWS

Entity Definitions

Lambda
Lambda is an AWS service discussed in this article.
EC2
EC2 is an AWS service discussed in this article.
S3
S3 is an AWS service discussed in this article.
RDS
RDS is an AWS service discussed in this article.
DynamoDB
DynamoDB is an AWS service discussed in this article.
CloudWatch
CloudWatch is an AWS service discussed in this article.
IAM
IAM is an AWS service discussed in this article.
VPC
VPC is an AWS service discussed in this article.

How to Implement a HIPAA-Compliant Architecture on AWS — An Engineer's Build Guide

Quick summary: A solutions architect's build guide for HIPAA on AWS. KMS key strategy, VPC isolation, RDS/S3/Lambda configuration patterns, IaC controls, and continuous validation — code-level decisions, not policy templates.

Key Takeaways

  • A solutions architect's build guide for HIPAA on AWS
  • KMS key strategy, VPC isolation, RDS/S3/Lambda configuration patterns, IaC controls, and continuous validation — code-level decisions, not policy templates
  • This guide is the engineering build manual — KMS keys, VPC layouts, IaC controls, and the AWS service configuration patterns that pass a HIPAA audit at the technical level
  • AWS is HIPAA-eligible, but compliance requires more than using AWS — it requires proper architecture, encryption, access controls, and continuous monitoring at the infrastructure layer
  • Building HIPAA-Compliant Healthcare on AWS
How to Implement a HIPAA-Compliant Architecture on AWS — An Engineer's Build Guide
Table of Contents

Looking for the audit-prep checklist? This guide is the engineering build manual — KMS keys, VPC layouts, IaC controls, and the AWS service configuration patterns that pass a HIPAA audit at the technical level. If you’re a Compliance Lead or Security Officer who needs to assemble the BAA, the documented Security Risk Assessment, workforce-training records, and the audit evidence package, read HIPAA on AWS: The Compliance Lead’s Audit-Ready Checklist instead.

This guide is written for solutions architects and platform engineers building HIPAA-eligible workloads. The focus is code- and config-level: which KMS key strategy survives a multi-account audit, how to lay out VPCs so PHI never crosses an unencrypted boundary, which RDS/S3/Lambda options are non-negotiable, and how to express all of it in Terraform or CDK so the architecture itself enforces compliance instead of relying on operator discipline.

HIPAA (Health Insurance Portability and Accountability Act) compliance is non-negotiable for healthcare organizations and vendors processing patient data. AWS is HIPAA-eligible, but compliance requires more than using AWS — it requires proper architecture, encryption, access controls, and continuous monitoring at the infrastructure layer.

This guide walks through building a HIPAA-compliant system at the architecture level: encrypting data at rest and in transit, centralizing audit logs, enforcing technical access controls via IAM and resource policies, validating compliance through Config rules, and producing the technical artifacts your audit lead will use as evidence.

Building HIPAA-Compliant Healthcare on AWS? FactualMinds helps healthcare organizations architect secure, compliant systems on AWS and navigate audit requirements. See our compliance services or talk to our team.

Step 1: Understand HIPAA Architecture Requirements

HIPAA compliance requires three layers:

Layer 1: Data Protection

  • Encryption at rest (data stored on disk)
  • Encryption in transit (data moving over network)
  • Access controls (who can read/write data)

Layer 2: Audit & Monitoring

  • CloudTrail logs (all API calls)
  • CloudWatch logs (application and system logs)
  • Config rules (resource compliance checking)
  • VPC Flow Logs (network traffic)

Layer 3: Incident Response & Governance

  • Incident response plan (documented, tested)
  • Data breach notification process
  • Business continuity/disaster recovery
  • Access reviews (quarterly)
  • Encryption key management

Example compliant architecture:

Patient Data

API Gateway (TLS, WAF)

Lambda (encrypted environment variables, no logging of PHI)

RDS (encrypted at rest, encrypted backups)

CloudTrail (all API calls logged)

S3 (encrypted, versioning, MFA delete enabled)

Audit Trail (CloudWatch Logs → S3 → Glacier for retention)

Step 2: Request a Business Associate Agreement (BAA)

Before deploying anything, sign a BAA with AWS.

  1. Go to AWS ConsoleComplianceBusiness Associate Addendum
  2. Click Request BAA
  3. Fill in organization info, expected data volumes
  4. Submit (AWS reviews in 5-10 business days)
  5. Once approved, sign electronically

Cost: Free. BAA is not a product; it’s a legal agreement that makes AWS services HIPAA-eligible for your account.

Step 3: Use HIPAA-Eligible AWS Services

Must-Use Services:

  • Compute: EC2, Lambda, Fargate
  • Storage: S3, EBS
  • Database: RDS (MySQL, PostgreSQL, Oracle), DynamoDB
  • Logging: CloudTrail, CloudWatch Logs
  • Encryption: KMS, Secrets Manager
  • Networking: VPC, API Gateway, NLB
  • Monitoring: Config, GuardDuty, Security Hub

Must-Avoid Services:

  • Alexa (voice, not HIPAA-eligible)
  • Amazon Connect (speech recognition)
  • Public S3 buckets (unless intentional)
  • Default VPC (use custom VPC for isolation)

Verify Your Architecture

Before building, audit the services:

  • No ineligible services
  • All storage encrypted by default
  • All data in transit uses TLS
  • Logging enabled on all resources

Step 4: Configure Encryption at Rest

S3 Buckets

Create S3 bucket with encryption enforced:

aws s3api create-bucket \
  --bucket my-hipaa-bucket \
  --region us-east-1

# Enable default encryption (AES-256)
aws s3api put-bucket-encryption \
  --bucket my-hipaa-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
      },
      "BucketKeyEnabled": true
    }]
  }'

# Block public access
aws s3api put-public-access-block \
  --bucket my-hipaa-bucket \
  --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

# Enable versioning (for audit trail)
aws s3api put-bucket-versioning \
  --bucket my-hipaa-bucket \
  --versioning-configuration Status=Enabled

# Enable MFA delete (requires root account MFA)
aws s3api put-bucket-versioning \
  --bucket my-hipaa-bucket \
  --versioning-configuration Status=Enabled,MFADelete=Enabled \
  --mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device 123456"

RDS Database

Create encrypted RDS instance:

aws rds create-db-instance \
  --db-instance-identifier hipaa-db \
  --db-instance-class db.t4g.medium \
  --engine postgres \
  --allocated-storage 100 \
  --storage-encrypted \
  --kms-key-id arn:aws:kms:us-east-1:123456789012:key/12345 \
  --backup-retention-period 30 \
  --copy-tags-to-snapshot \
  --enable-cloudwatch-logs-exports postgresql \
  --storage-type gp3 \
  --no-publicly-accessible \
  --db-subnet-group-name hipaa-db-subnet-group

EBS Volumes

Encrypt all EC2 EBS volumes:

# Enable default EBS encryption in region
aws ec2 enable-ebs-encryption-by-default --region us-east-1
aws ec2 create-volume \
  --size 100 \
  --availability-zone us-east-1a \
  --volume-type gp3 \
  --encrypted \
  --kms-key-id arn:aws:kms:us-east-1:123456789012:key/12345

Step 5: Configure Encryption in Transit

API Gateway (TLS Enforced)

# Create REST API with TLS enforced
aws apigateway create-rest-api \
  --name hipaa-api \
  --endpoint-configuration types=REGIONAL

# Create deployment with TLS 1.2+ only
aws apigateway create-deployment \
  --rest-api-id xxxxx \
  --stage-name prod \
  --stage-variables {"minTlsVersion": "TLS1.2"}

RDS Connection (SSL/TLS)

import psycopg2
import ssl

connection = psycopg2.connect(
    host="hipaa-db.xxxxx.us-east-1.rds.amazonaws.com",
    user="postgres",
    password="password",
    database="hipaa_db",
    sslmode="require"  # Enforce TLS
)

Lambda Environment Variables (Encrypted)

import boto3
import json

secrets_client = boto3.client('secretsmanager', region_name='us-east-1')

# Store PHI-related secrets in Secrets Manager (encrypted by default)
secret_response = secrets_client.create_secret(
    Name='hipaa/db-password',
    SecretString=json.dumps({'password': 'xxxxxx'}),
    KmsKeyId='arn:aws:kms:us-east-1:123456789012:key/12345'
)

# Lambda retrieves at runtime
def lambda_handler(event, context):
    secret = secrets_client.get_secret_value(SecretId='hipaa/db-password')
    return {'statusCode': 200}

Step 6: Configure Audit Logging

CloudTrail (API Calls)

Enable CloudTrail to log all API activity:

aws cloudtrail create-trail \
  --name hipaa-trail \
  --s3-bucket-name hipaa-cloudtrail-logs \
  --is-multi-region-trail

# Enable logging
aws cloudtrail start-logging --trail-name hipaa-trail

# Enable CloudTrail Insights (detects unusual activity)
aws cloudtrail put-insight-selectors \
  --trail-name hipaa-trail \
  --insight-selectors '{"InsightType": "ApiCallRateInsight"}'

CloudWatch Logs (Application & System Logs)

import logging
import json
from datetime import datetime

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def log_hipaa_event(action, user_id, resource_id):
    """Log HIPAA-relevant events without logging PHI"""
    log_entry = {
        'timestamp': datetime.utcnow().isoformat(),
        'action': action,
        'user_id': user_id,
        'resource_id': resource_id,
        'status': 'success'
    }
    logger.info(json.dumps(log_entry))

# In Lambda or application
log_hipaa_event('patient_record_accessed', 'user-123', 'patient-456')

VPC Flow Logs (Network Traffic)

aws ec2 create-flow-logs \
  --resource-type VPC \
  --resource-ids vpc-12345 \
  --traffic-type ALL \
  --log-destination-type cloud-watch-logs \
  --log-group-name /aws/vpc/hipaa-flow-logs

CloudWatch Alarms (Anomaly Detection)

aws cloudwatch put-metric-alarm \
  --alarm-name "Unauthorized-S3-Access" \
  --alarm-description "Alert on unusual S3 access patterns" \
  --metric-name UnauthorizedAPICallsEventCount \
  --namespace CloudTrailMetrics \
  --statistic Sum \
  --period 300 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:hipaa-alerts

Step 7: Enforce Access Controls

IAM Policy (Least Privilege)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadPatientData",
      "Effect": "Allow",
      "Action": ["rds:DescribeDBInstances", "secretsmanager:GetSecretValue"],
      "Resource": [
        "arn:aws:rds:us-east-1:123456789012:db:hipaa-db",
        "arn:aws:secretsmanager:us-east-1:123456789012:secret:hipaa/*"
      ],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "10.0.0.0/8"
        }
      }
    }
  ]
}

VPC Security Groups (Network Isolation)

# Only allow database access from app tier
aws ec2 authorize-security-group-ingress \
  --group-id sg-db \
  --protocol tcp \
  --port 5432 \
  --source-security-group-id sg-app

# Deny all inbound by default
aws ec2 describe-security-groups \
  --group-ids sg-db \
  --query 'SecurityGroups[0].IpPermissions' empty (no inbound rules except app tier)

Step 8: Validate HIPAA Compliance

AWS Config Rules

Set up Config rules to continuously check compliance:

aws configservice put-config-rule --config-rule '{
  "ConfigRuleName": "s3-bucket-server-side-encryption-enabled",
  "Description": "S3 buckets must have encryption enabled",
  "Source": {
    "Owner": "AWS",
    "SourceIdentifier": "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
  }
}'

aws configservice put-config-rule --config-rule '{
  "ConfigRuleName": "encrypted-volumes",
  "Description": "EBS volumes must be encrypted",
  "Source": {
    "Owner": "AWS",
    "SourceIdentifier": "ENCRYPTED_VOLUMES"
  }
}'

aws configservice put-config-rule --config-rule '{
  "ConfigRuleName": "rds-encryption-enabled",
  "Description": "RDS must have encryption enabled",
  "Source": {
    "Owner": "AWS",
    "SourceIdentifier": "RDS_STORAGE_ENCRYPTED"
  }
}'

Security Hub (Compliance Dashboard)

Enable AWS Security Hub for continuous monitoring:

aws securityhub create-hub --region us-east-1

# Enable HIPAA standards
aws securityhub batch-enable-standards \
  --standards-subscription-requests '[{
    "StandardsArn": "arn:aws:securityhub:us-east-1::standards/aws-foundational-security-best-practices/v/1.0.0"
  }]'

View compliance status in the console: AWS Security HubComplianceHIPAA Status

Step 9: Production Compliance Patterns

Pattern 1: Data Classification

Tag all resources with data sensitivity:

aws ec2 create-tags --resources vol-12345 --tags Key=DataClassification,Value=PHI

# Use tags to restrict access
aws iam put-role-policy --role-name app-role --policy-name tag-policy --policy-document '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "ec2:*",
    "Resource": "*",
    "Condition": {
      "StringEquals": {
        "ec2:ResourceTag/DataClassification": "PHI"
      }
    }
  }]
}'

Pattern 2: Audit Trail Retention

Archive logs to Glacier for 7-year retention (HIPAA requirement):

# S3 Lifecycle policy for CloudTrail logs
aws s3api put-bucket-lifecycle-configuration \
  --bucket hipaa-cloudtrail-logs \
  --lifecycle-configuration '{
    "Rules": [{
      "ID": "Archive-CloudTrail-Logs",
      "Status": "Enabled",
      "Transitions": [{
        "Days": 90,
        "StorageClass": "GLACIER"
      }],
      "Expiration": {
        "Days": 2555
      }
    }]
  }'

Pattern 3: Quarterly Access Reviews

import boto3
from datetime import datetime

iam = boto3.client('iam')

def audit_iam_access():
    """Generate quarterly IAM access audit"""
    users = iam.list_users()['Users']

    for user in users:
        access_keys = iam.list_access_keys(UserName=user['UserName'])
        inline_policies = iam.list_user_policies(UserName=user['UserName'])

        print(f"User: {user['UserName']}")
        print(f"  Access Keys: {len(access_keys['AccessKeyMetadata'])}")
        print(f"  Inline Policies: {inline_policies['PolicyNames']}")
        print(f"  Last Used: {access_keys['AccessKeyMetadata'][0].get('CreateDate', 'N/A')}")
        print()

audit_iam_access()

Common Mistakes to Avoid

  1. Storing PHI in application logs

    • logger.info(f"Patient {patient.name} with SSN {patient.ssn} logged in")
    • logger.info(f"Patient {patient_id} logged in")
    • Log user IDs and actions, not sensitive data
  2. Using unencrypted backups

    • Every backup must be encrypted
    • Verify StorageEncrypted=True on RDS snapshots
  3. Forgetting to enable versioning

    • S3 versioning allows audit trail recovery
    • Enable on all HIPAA buckets
  4. Not rotating encryption keys

    • Rotate KMS keys annually
    • AWS KMS handles this automatically if enabled
  5. Leaving default AWS settings

    • Default VPC is public (create custom VPC)
    • Default security groups allow all inbound (restrict)
    • Default S3 buckets don’t block public (enable)

Compliance Checklist

Before going live:

  • BAA signed with AWS
  • All data encrypted at rest (S3, RDS, EBS)
  • All data encrypted in transit (TLS)
  • CloudTrail enabled and logging
  • CloudWatch Logs configured
  • VPC Flow Logs enabled
  • Security groups restrict access
  • IAM policies follow least privilege
  • AWS Config rules pass (encryption, logging)
  • Security Hub enabled and monitoring
  • Incident response plan documented
  • Data breach notification process in place
  • Disaster recovery tested
  • Quarterly access reviews scheduled

Next Steps

  1. Request BAA (5-10 days)
  2. Set up CloudTrail and CloudWatch Logs
  3. Encrypt all data (S3, RDS, EBS)
  4. Enable AWS Config and Security Hub
  5. Schedule quarterly compliance audits
  6. Test incident response plan
  7. Talk to FactualMinds if you need help auditing or maintaining HIPAA compliance on AWS
PP
Palaniappan P

AWS Cloud Architect & AI Expert

AWS-certified cloud architect and AI expert with deep expertise in cloud migrations, cost optimization, and generative AI on AWS.

AWS ArchitectureCloud MigrationGenAI on AWSCost OptimizationDevOps

Ready to discuss your AWS strategy?

Our certified architects can help you implement these solutions.

Recommended Reading

Explore All Articles »