---
title: How to Implement a HIPAA-Compliant Architecture on AWS — An Engineer's Build Guide
description: 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.
url: https://www.factualminds.com/blog/how-to-implement-hipaa-compliant-architecture-aws/
datePublished: 2026-04-03T00:00:00.000Z
dateModified: 2026-04-27T00:00:00.000Z
author: Palaniappan P
category: Security & Compliance
tags: how-to-guide, hipaa, healthcare, compliance, security, aws, architecture
---

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

> 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.

> **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](/blog/hipaa-on-aws-complete-compliance-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](/services/cloud-compliance-services/) or [talk to our team](/contact-us/).

## 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 Console** → **Compliance** → **Business 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:

```bash
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:

```bash
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:

```bash
# 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)

```bash
# 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)

```python
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)

```python
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:

```bash
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)

```python
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)

```bash
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)

```bash
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)

```json
{
  "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)

```bash
# 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:

```bash
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:

```bash
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 Hub** → **Compliance** → **HIPAA Status**

## Step 9: Production Compliance Patterns

### Pattern 1: Data Classification

Tag all resources with data sensitivity:

```bash
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):

```bash
# 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

```python
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](/contact-us/) if you need help auditing or maintaining HIPAA compliance on AWS

## FAQ

### What does HIPAA compliance on AWS actually mean?
HIPAA (Health Insurance Portability and Accountability Act) requires healthcare organizations to protect patient data (Protected Health Information, or PHI) through encryption, access controls, and audit logging. AWS compliance means: (1) AWS signs a Business Associate Agreement (BAA) committing to HIPAA requirements, (2) You use HIPAA-eligible AWS services (EC2, RDS, S3, etc.), (3) You configure those services to enforce encryption, logging, access controls, and (4) You audit your own configuration quarterly. AWS handles infrastructure; you handle application and data configuration. HIPAA is NOT a checkbox — it requires ongoing monitoring and evidence collection.

### Which AWS services are HIPAA-eligible?
AWS publishes a list of HIPAA-eligible services: EC2, RDS, DynamoDB, S3, Lambda, CloudTrail, CloudWatch, KMS, Secrets Manager, VPC, API Gateway, and ~80 others. Ineligible services: Alexa, Amazon Connect (speech), public datasets. When building a HIPAA app, use only eligible services. For example, if you use Alexa for patient voice commands, you cannot claim HIPAA compliance (even if everything else is compliant). Check the AWS HIPAA-eligible service list before architecture decisions.

### What happens if I store PHI in an unencrypted S3 bucket?
HIPAA breach. If audited or hacked, you must notify all affected patients, pay fines ($100-$50,000 per record), and face legal liability. Encrypting S3 is trivial (one setting), so there's no excuse. Same for databases, logs, and backups — encryption-at-rest is non-negotiable. Encryption-in-transit (TLS) is also required for all data movement (API calls, database connections, log shipping).

### Do I need a Business Associate Agreement with AWS?
Yes. If you process PHI on AWS, you must sign a BAA before deploying anything. The BAA commits AWS to HIPAA requirements and defines liability if AWS is breached. The process: (1) Go to AWS Business Associate Addendum portal, (2) Request BAA (takes 5-10 business days), (3) Sign, (4) Deploy HIPAA-eligible services. No BAA = no HIPAA compliance, even if you encrypt everything. If you're a startup or contractor building for a healthcare client, the client signs the BAA (you're the business associate; they're the covered entity).

### How often do I need to audit HIPAA compliance?
At minimum, quarterly. In practice, continuously via automated controls. Set up: (1) AWS Config rules to detect unencrypted resources, (2) CloudTrail for all API calls, (3) Access reviews (who has access to what), (4) Penetration testing (annually), (5) Incident response plan (test it). If audited by HHS (Department of Health and Human Services), you must demonstrate continuous compliance, not just a point-in-time audit.

---

*Source: https://www.factualminds.com/blog/how-to-implement-hipaa-compliant-architecture-aws/*
