Interview Setup
Interview Prompt
Design a centralized Secrets Manager and KMS (HashiCorp Vault / AWS Secrets Manager style) for 100K services, 10M secret versions, and 50K peak secret reads per second. Support API keys, database passwords, and TLS certificates with envelope encryption, dynamic short-lived credentials, rotation without downtime, and a complete audit trail. Enforce multi-tenant isolation, RBAC, and break-glass emergency access.
Clarifying Questions (ask before designing)
| Question | Why it matters |
|---|---|
| Static secrets vs dynamic secrets: which is the hot path? | Static secrets (long-lived API keys) dominate read volume at 50K requests per second. Dynamic secrets add lease management, database admin connectivity, and revoker daemons, which are designed as separate subsystems. |
| Do we build the HSM or integrate with cloud KMS? | Interview scope focuses on designing envelope encryption workflows and key hierarchies. Root keys reside inside FIPS 140-3 Level 3 or an equivalent certified HSM boundary, and our service orchestrates Encrypt and Decrypt APIs rather than manufacturing physical appliances. |
| How do services authenticate to fetch secrets? | Workload identity uses mTLS (SPIFFE), IAM roles (AWS IRSA), or OIDC tokens from an identity provider. Services should never rely on long-lived bootstrap secrets stored in plain configuration files. |
| What does rotation without downtime mean for callers? | Secrets are versioned with a grace period where older versions remain readable for 24 to 72 hours while workloads pick up the new version. Dynamic secrets rotate by issuing fresh leases while allowing older leases to expire naturally. |
| Multi-tenant: shared infrastructure or dedicated clusters? | A shared control plane with strict tenant isolation and per-tenant customer master keys reflects standard cloud architectures. Regulated enterprise tenants may additionally mandate dedicated HSM partitions as a premium tier. |
Scope
In scope
- Centralized storage for API keys, DB passwords, TLS certificates
- Envelope encryption with KMS master keys (CMK) in HSM
- Dynamic secrets: short-lived database credentials with lease TTL
- Automated rotation with zero-downtime version grace period
- Immutable audit log of every secret access (read, write, deny)
- Multi-tenant isolation, RBAC, break-glass emergency access
- Cross-region replication for disaster recovery
Out of scope (state explicitly)
- Building HSM hardware or FIPS certification process
- Full identity provider (integrate via workload IAM and OIDC)
- Certificate Authority (CA) issuance (store PEM bundles, do not operate public CA)
- Secrets scanning in git repos (separate product area)
Functional Requirements
Start by clarifying whether static secrets, dynamic short-lived credentials, or both dominate the hot path. Establish envelope encryption workflows, rotation grace periods, and break-glass policies before discussing KMS hardware.
- Static secret storage: Store API keys, database passwords, TLS certificate bundles, and arbitrary key-value payloads with versioning.
- Envelope encryption: Encrypt all secrets at rest with per-version data encryption keys wrapped by customer master keys inside hardware security modules.
- Secret retrieval: Authenticated workloads retrieve secret values by identifier, path, or alias, with optional explicit version pinning or current version pointers.
- Dynamic secrets: Provision ephemeral database credentials with configurable lease time-to-live and automated background revocation.
- Automated rotation: Execute scheduled rotation with upstream verification hooks and zero-downtime version grace periods.
- Audit logging: Maintain an immutable audit record of every read, write, denial, rotation, and break-glass access with principal, IP, and distributed trace metadata.
- Multi-tenant isolation: Enforce strict tenant boundaries at API routing, metadata storage, blob storage, and KMS key policy tiers.
- Role-based access control: Evaluate path-based policies with explicit deny semantics and condition validation.
- Break-glass access: Support time-bound emergency access requiring dual human approval and elevated security alerts.
- Cross-region replication: Keep secrets readable in secondary disaster recovery regions within strict recovery point objectives.
Non-Functional Requirements
Interviewers will stress-test read-path availability at 99.99%, as a secrets outage halts the entire fleet. They will also inquire how to maintain 50K reads per second when HSM decryption requires roughly 5 to 15ms (where DEK caching and horizontal read replicas provide the answer).
- Security: Plaintext secrets exist only transiently in authorized service memory during decryption and response handling. They are never persisted to disk, durable storage, or logs, are zeroized as soon as practical, and all internal traffic enforces mutual TLS.
- Scale: 100K services, 10M secret versions, and 50K peak reads per second.
- Availability: 99.99% availability on the read path because secrets outages trigger cascading service outages.
- Latency: p99 latency under 50ms for cached reads and under 200ms on cold paths requiring KMS decryption.
- Durability: Zero secret loss, backed by Write-Ahead Logging (WAL), blob versioning, and replicated storage.
- Compliance: Adhere to SOC 2, PCI DSS cardholder environment requirements, and 7-year audit retention mandates.
- Observability: Distributed Tracing on every API call, tracking KMS latency, cache hit rates, and rotation success metrics.
Capacity Estimations
HSM decrypt throughput forms the primary read-path bottleneck, making DEK cache hit rate optimization essential before scaling API replicas. An audit event volume of roughly 55K events per second drives Kafka partition sizing and ClickHouse retention tiering.
| Metric | Calculation | Value |
|---|---|---|
| Registered services / workloads | Given | 100K |
| Secret versions (total) | Given | 10M |
| Peak secret reads / sec | Given | 50K |
| Avg secret payload size | API keys ~256 B, TLS bundles ~8 KB, use 2 KB avg | ~2 KB |
| Encrypted blob storage | 10M versions x 2 KB | ~20 GB (+ replicas) |
| Metadata rows | 10M versions + 100K secret names | ~10M rows |
| KMS decrypt ops / sec (peak) | 1 decrypt per read (DEK unwrap) | 50K |
| Audit events / sec (peak) | 1 event per read + writes/rotations | ~55K |
| Audit storage / day | 55K x 86400 x 500 B | ~2.4 TB/day (compressed ~400 GB) |
| Dynamic secret leases active | 10% of services x 2 leases avg | ~20K concurrent |
| Rotation jobs / day | 5% of secrets on 30-day cycle | ~17K rotations/day |
The read path scales horizontally: 50 API replicas handle roughly 1K RPS each when backed by a Redis DEK cache. The KMS HSM cluster is sized for approximately 10K synchronous decrypts per second, with the remaining 40K RPS served from cache (achieving roughly 80% steady-state hit rate). The audit pipeline leverages 128 Kafka partitions to ingest 55K events per second into ClickHouse MergeTree tables with 7-year retention tiering to cold storage.
Architecture Diagram
Walk through envelope encryption first because it establishes the foundational security model for the entire system. Secrets Manager acts as a control plane for credential lifecycles, integrating with an Auth System (OAuth & SSO) for workload identity while ensuring plaintext credentials never persist to durable storage outside the authorized service memory required to serve a request.
A random data encryption key encrypts each secret version with AES-GCM, and the KMS wraps this key using a customer master key inside a hardware security module. On reads, the system unwraps the key, decrypts the blob, returns the plaintext payload, and immediately zeroizes memory. Customer master key rotation re-wraps data encryption keys without touching secret payloads at scale.
The architecture spans three primary pipelines: static secret versioned blobs in object storage, a dynamic secrets engine managing lease-based database credentials, and an immutable audit bus streaming all read, write, and denial events asynchronously to Kafka.
In the room
Draw the envelope encryption diagram before detailing API endpoints: data encryption keys protect payloads, customer master keys in the HSM wrap data encryption keys, and plaintext keys never hit disk. When asked about rotation, walk through versioned secrets with a 24 to 72 hour grace period rather than in-place password swaps.
Envelope Encryption Flow
Component Deep Dives
1. Key Hierarchy (KMS)
Key hierarchies, envelope boundaries, and rotation grace periods form the operational focus of enterprise secrets architectures.
The cryptographic architecture organizes into three distinct tiers: root keys never export from hardware boundaries, customer master keys wrap data encryption keys, and data encryption keys protect secret payloads.
- Root KMS Key (RKK): Generated inside hardware security modules and physically non-exportable, signing and wrapping regional customer master keys within FIPS 140-3 Level 3 or an equivalent certified HSM boundary boundaries.
- Customer Master Key (CMK): Provisioned per tenant or per environment, used exclusively to wrap and unwrap data encryption keys rather than encrypting secret payloads directly.
- Data Encryption Key (DEK): A random 256-bit AES key generated per secret version, encrypting payloads via AES-256-GCM and stored only in wrapped ciphertext form.
- CMK rotation: Annual automated rotation provisions a new key version, while a background re-wrap job unwraps data encryption keys using the previous version and re-wraps them under the new version without exposing secret plaintexts.
2. Secret Lifecycle API
Every lifecycle operation is authenticated and authorized against path policies. Mutations are durably committed before returning, while asynchronous audit publication and indexing do not extend the request path unnecessarily.
- Create and update: Accepts secret payloads over TLS, executes envelope encryption, persists the ciphertext blob and metadata row, designates the version as CURRENT, and emits an audit event.
- Read: Validates workload authorization, loads version metadata, requests KMS to unwrap the data encryption key, decrypts the blob in memory, emits an audit event, and returns the plaintext payload while zeroizing volatile memory.
- List: Returns metadata collections filtered by tenant namespace, omitting secret values to prevent bulk exfiltration.
- Delete: Enforces a soft-delete retention window of 30 days. After the retention and backup lifecycle requirements are satisfied, deleting the wrapped data encryption key provides cryptographic erasure while leaving the underlying ciphertext irrecoverable.
- Idempotency and audit durability: Create and update honor an
Idempotency-Key. Read and deny events are appended to a local durable WAL or spool before the response completes, then published to Kafka asynchronously with retry and replay. If durable audit staging is unavailable, the request fails rather than silently losing the event.
3. Dynamic Secrets Engine ⭐
Dynamic secrets eliminate static passwords by provisioning ephemeral database roles on demand with automatic lease expiration.
POST /v1/dynamic/database/creds (lease request)
1. AuthZ: principal must have dynamic-creds:issue on database role
2. Dynamic engine connects to target DB with stored admin creds (from static secret)
3. CREATE USER svc_abc123 WITH PASSWORD 'random' VALID UNTIL now() + interval '1 hour'
4. GRANT readwrite TO svc_abc123
5. Store lease record: { lease_id, username, expires_at, secret_id_ref }
6. Return { username, password, lease_id, lease_duration: 3600 }
7. Audit: dynamic_lease.issued
Renew: POST /v1/dynamic/leases/{lease_id}/renew: extends VALID UNTIL (max 24h total)
Revoke: DELETE /v1/dynamic/leases/{lease_id}: atomically transition the lease to revoke_pending, then DROP USER and mark revoked, where retries are idempotent
Revoker daemon (every 30s):
SELECT leases WHERE expires_at < NOW() AND status = 'active'
→ claim active lease with compare-and-set → DROP USER → mark revoked only after successful revocation → audit dynamic_lease.revokedBy provisioning unique database users per workload instance, the blast radius of a credential leak is confined to a single short-lived lease. The trade-off requires direct network connectivity from the secrets cluster to target database engines and bootstrapping admin credentials stored securely within the envelope store.
4. Rotation Scheduler
Zero-downtime rotation requires versioned credentials with overlapping grace windows so existing workload instances continue functioning while new instances adopt fresh credentials.
Zero-downtime rotation for static secret (e.g., DB password): T0: Secret v3 is CURRENT (password: old_pw) T1: Rotation job generates new_pw, creates v4 as PENDING T2: Rotation hook updates upstream (e.g., ALTER USER in PostgreSQL with admin creds) T3: Smoke test: dynamic engine verifies new_pw works (SELECT 1) T4: Transactionally CAS v3 CURRENT → v4 CURRENT and v3 → DEPRECATED (grace_until = T4 + 48h) T5: Workloads still on v3 succeed until grace ends. The SDK polls version every 5 min, and repeated retries are idempotent T6: After grace: v3 → DISABLED (reads return 410). Audit confirms zero v3 reads before destructive cleanup Rollback: if smoke test fails at T3, delete v4, alert operator, v3 remains CURRENT. Every state transition is guarded by the secret version and expected current-version value so retries cannot promote a stale version. Dynamic secret rotation (Vault-style): - Each lease is independent. There is no shared password across services - Lease TTL is 1h. Renewal is allowed up to max_ttl 24h - On expiry: background revoker claims the lease with compare-and-set, DROP USER in DB, then marks it revoked. Failed DB revocation remains retryable
- Rotation policies: Specify rotation intervals, grace period durations, and webhook target URLs for custom upstream systems.
- Coordination and idempotency: Leverages Leader Election to coordinate one scheduler per secret, while transactional compare-and-set state transitions make retries safe if a worker crashes after an upstream mutation.
- Verification smoke testing: Prohibits promoting a new version to CURRENT until an end-to-end verification query succeeds against the target database.
5. Policy Engine & RBAC
Path-based access policies enforce explicit deny precedence and tenant boundary verification before evaluating allow rules.
Policy example (path-based, Vault ACL style):
path "secret/data/prod/db/*" {
capabilities = ["read"]
allowed_principals = ["role:payment-service", "role:order-service"]
}
path "secret/data/prod/db/admin" {
capabilities = ["read"]
allowed_principals = ["role:break-glass"]
require_mfa = true
max_ttl = 3600
}
Evaluation order:
1. Deny rules (explicit deny wins)
2. Tenant boundary check (principal.tenant_id == resource.tenant_id)
3. Allow rules by longest path match
4. Default deny
Cache: policy decisions in Redis (TTL 60s), including a policy version in cache keys and invalidating through pub/sub. A durable policy version check prevents stale allows after a subscriber reconnects6. Audit Pipeline
Audit durability is non-negotiable. All access attempts, including rejected requests, are durably staged before the request is considered complete and then published asynchronously to Kafka so the Kafka path does not block the read path.
Topic: secret-access-events
Partitions: 128 (partition by tenant_id for per-tenant ordering during compliance export)
Retention: 7 days hot replay buffer, while compliance retention lives in immutable WORM storage for 7 years
Events: secret.read, secret.write, secret.rotate, dynamic_lease.issued, dynamic_lease.revoked,
break_glass.access, kms.decrypt, policy.denied
Payload: { event_id, tenant_id, secret_id, version, principal_id, principal_ip, trace_id, outcome, timestamp }
Consumer groups:
1. audit-indexer: ClickHouse immutable store, compliance dashboards
2. siem-forwarder: Splunk/Datadog security analytics
3. anomaly-detector: bulk read, geo anomaly, break-glass usage
4. billing-metering: API call counts per tenant (optional)
Sync path: GET /secrets/{id} → authZ → load ciphertext metadata → unwrap DEK if not cached → decrypt → durable audit staging → async Kafka publish
Async path: rotation scheduler, cross-region replication, re-wrap jobs
DLQ: secret-access-events-dlq (alert on any message because audit loss is P0)Audit records correlate with Distributed Tracing via a trace identifier on every event. The compliance export API allows authorized auditors to extract cryptographically signed logs partitioned by tenant.
7. Cross-Region Replication and Failover
Multi-region deployments operate with active-active read capacity across regions, while mutation leadership relies on Leader Election to ensure single-region write coordination per secret.
- Metadata replication: Synchronizes PostgreSQL state or CockroachDB tables across regions asynchronously for the normal path, while critical writes can wait for a configured replication quorum when the RPO requires it.
- Blob replication: Leverages cross-region object storage replication with eventual consistency bounded by a five-second replication lag SLO.
- Multi-region keys: Uses provider-supported multi-region KMS keys or an equivalent regional key hierarchy so each region can perform local cryptographic operations without shipping secret plaintext across regions.
- Failover coordination: Follower regions serve local read traffic during normal operation and promote to primary coordinators upon leader loss.
API Design
Workloads authenticate using OIDC tokens or mutual TLS rather than hardcoded bootstrap passwords. Every response propagates trace headers conforming to Distributed Tracing. API semantics also follow the API Contract and Integration Design principles for idempotency, error contracts, and versioning. Dynamic secret responses include lease identifiers for renewal and revocation.
Get Secret Value
GET /v1/secrets/prod/db/payment-password?version=current
Authorization: Bearer <workload_oidc_token>
X-Request-Id: req_uuid
X-Trace-Id: trace_abc123
Response: 200 OK
{
"secret_id": "sec_payment_db",
"version": 7,
"value": "s3cr3t_p@ssw0rd",
"created_at": "2026-06-15T10:00:00Z",
"rotation_next": "2026-07-15T10:00:00Z",
"lease_id": null
}
Dynamic secret response includes lease:
{
"username": "svc_k8s_pod_abc",
"password": "xK9#mQ2...",
"lease_id": "lease_uuid",
"lease_duration": 3600,
"renewable": true
}Create / Update Secret
PUT /v1/secrets/prod/api/stripe-key
Authorization: Bearer <admin_token>
Idempotency-Key: idem-uuid-12345
Content-Type: application/json
{
"value": "sk_live_...",
"description": "Stripe production API key",
"rotation_policy": {
"automatic": true,
"interval_days": 90,
"grace_period_hours": 48
}
}
Response: 201 Created
{
"secret_id": "sec_stripe_key",
"version": 3,
"arn": "arn:secrets:us-east-1:tenant:secret/prod/api/stripe-key"
}Issue Dynamic Database Credentials
POST /v1/dynamic/database/creds
Authorization: Bearer <workload_token>
{
"role": "readonly",
"database": "payments",
"ttl_seconds": 3600
}
Response: 200 OK
{
"username": "v-dynamic-ro-abc123",
"password": "generated_password",
"lease_id": "lease_uuid",
"lease_duration": 3600
}
POST /v1/dynamic/leases/lease_uuid/renew
Response: 200 { "lease_duration": 3600, "renewable": true }
DELETE /v1/dynamic/leases/lease_uuid
Response: 204 No ContentDynamic credential issuance is intentionally non-idempotent because each successful request creates a distinct lease and database principal. Renew and revoke are idempotent, and revocation uses a lease state transition before changing the target database so concurrent renewals cannot extend a lease that has already entered revoke_pending.
Break-Glass Access Request
POST /v1/break-glass/request
Authorization: Bearer <operator_token>
{
"secret_id": "sec_prod_db_root",
"incident_ticket": "INC-98765",
"justification": "Production DB failover requires root creds",
"approver_ids": ["mgr_uuid_1", "mgr_uuid_2"]
}
Response: 202 Accepted (pending dual approval)
{
"request_id": "bg_req_uuid",
"status": "pending_approval"
}
After both approvers confirm:
GET /v1/secrets/prod/db/root
Authorization: Bearer <break_glass_token>
Returns secret, records audit tagged break_glass=true, and fires SIEM alertCommon Error Responses
400 Bad Request: invalid input, missing required fields, or malformed JSON payload 401 Unauthorized: missing or invalid authentication token or API key 403 Forbidden: authenticated caller lacks required permissions for this resource 404 Not Found: requested resource ID does not exist 409 Conflict: duplicate write or version conflict, retry with a unique idempotency key 422 Unprocessable Entity: syntactically valid request failed semantic business validation 429 Too Many Requests: rate limit quota exceeded, client should honor Retry-After header 500 Internal Error: unexpected server failure, retry safely with an idempotency key 503 Service Unavailable: downstream dependency is unavailable or overloaded, retry with exponential backoff 422 Unprocessable Entity: password does not meet security requirements or MFA verification is required 423 Locked: account temporarily locked after repeated failed login attempts
Data Model
PostgreSQL: Secrets Metadata
CREATE TABLE secrets (
secret_id UUID PRIMARY KEY,
tenant_id UUID NOT NULL,
path VARCHAR(512) NOT NULL, -- e.g. prod/db/payment-password
secret_type VARCHAR(32) NOT NULL, -- static, dynamic, certificate
current_version INT NOT NULL DEFAULT 1,
rotation_policy JSONB,
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL,
deleted_at TIMESTAMPTZ,
UNIQUE (tenant_id, path)
);
CREATE TABLE secret_versions (
version_id UUID PRIMARY KEY,
secret_id UUID NOT NULL REFERENCES secrets(secret_id),
version_num INT NOT NULL,
status VARCHAR(16) NOT NULL, -- current, deprecated, disabled, pending
cmk_id UUID NOT NULL,
cmk_version INT NOT NULL,
blob_ref VARCHAR(512) NOT NULL, -- s3://bucket/tenant/secret/v7
wrapped_dek BYTEA NOT NULL,
grace_until TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL,
UNIQUE (secret_id, version_num)
);
CREATE INDEX idx_secrets_tenant ON secrets(tenant_id, path);
CREATE INDEX idx_versions_current ON secret_versions(secret_id, status)
WHERE status IN ('current', 'deprecated');PostgreSQL: Dynamic Leases & Policies
CREATE TABLE dynamic_leases (
lease_id UUID PRIMARY KEY,
secret_id UUID NOT NULL,
tenant_id UUID NOT NULL,
principal_id VARCHAR(256) NOT NULL,
target_username VARCHAR(128) NOT NULL,
issued_at TIMESTAMPTZ NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
max_ttl_seconds BIGINT NOT NULL,
status VARCHAR(16) NOT NULL -- active, revoke_pending, revoked, expired
);
CREATE INDEX idx_dynamic_leases_expiry ON dynamic_leases(status, expires_at);
CREATE TABLE policies (
policy_id UUID PRIMARY KEY,
tenant_id UUID NOT NULL,
name VARCHAR(128) NOT NULL,
path_pattern VARCHAR(512) NOT NULL,
capabilities TEXT[] NOT NULL, -- read, write, delete, list
principal_roles TEXT[] NOT NULL,
conditions JSONB -- require_mfa, max_ttl
);
CREATE TABLE kms_keys (
cmk_id UUID PRIMARY KEY,
tenant_id UUID NOT NULL,
alias VARCHAR(256),
hsm_key_ref VARCHAR(512) NOT NULL,
current_version INT NOT NULL DEFAULT 1,
rotation_enabled BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ NOT NULL
);Redis: DEK Cache
dek:{tenant_id}:{secret_id}:{version} -> app-encrypted unwrapped DEK bytes, TTL 60s
policy:{tenant_id}:{principal_hash}:{path} -> allow|deny, TTL 60s
rate:{tenant_id}:{principal_id}:read -> counter, TTL 60s (100/min default)ClickHouse: Audit Events (immutable)
CREATE TABLE secret_audit_events (
event_id UUID,
tenant_id UUID,
secret_id UUID,
version Nullable(Int32),
event_type LowCardinality(String),
principal_id String,
principal_ip String,
trace_id String,
outcome Enum8('success' = 1, 'denied' = 2, 'error' = 3),
break_glass UInt8 DEFAULT 0,
metadata String,
event_time DateTime64(3)
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_time)
ORDER BY (tenant_id, event_time, secret_id)
TTL event_time + INTERVAL 7 YEAR;Event Bus Design (Kafka)
Topic: secret-access-events
Partitions: 128 (partition by tenant_id for per-tenant ordering during compliance export)
Retention: 7 days hot replay buffer, while compliance retention lives in immutable WORM storage for 7 years
Events: secret.read, secret.write, secret.rotate, dynamic_lease.issued, dynamic_lease.revoked,
break_glass.access, kms.decrypt, policy.denied
Payload: { event_id, tenant_id, secret_id, version, principal_id, principal_ip, trace_id, outcome, timestamp }
Consumer groups:
1. audit-indexer: ClickHouse immutable store, compliance dashboards
2. siem-forwarder: Splunk/Datadog security analytics
3. anomaly-detector: bulk read, geo anomaly, break-glass usage
4. billing-metering: API call counts per tenant (optional)
Sync path: GET /secrets/{id} → authZ → load ciphertext metadata → unwrap DEK if not cached → decrypt → durable audit staging → async Kafka publish
Async path: rotation scheduler, cross-region replication, re-wrap jobs
DLQ: secret-access-events-dlq (alert on any message because audit loss is P0)Fault Tolerance
Fault Tolerance Scenarios
| Concern | Solution |
|---|---|
| KMS or HSM unavailable during read | Cache unwrapped DEKs in regional Redis instances as app-encrypted values with a short TTL and encryption at rest. Reads can use a locally decrypted cached DEK for hot secrets, while failing closed on cache misses during KMS outages. Multi-AZ HSM clusters ensure automated hardware failover. |
| Rotation breaks running workloads | Versioned secrets maintain the new version as CURRENT while keeping the previous version DEPRECATED with a 24 to 72 hour grace window. Clients use version-aware SDKs or polling. Dynamic secrets leave existing leases valid until TTL expiration rather than executing in-place password swaps. |
| Cross-region read after write inconsistency | Metadata replicates via PostgreSQL logical replication, while blob storage leverages cross-region object replication. Read-your-writes requests route to the regional primary or wait for a replication watermark before serving from a replica. General replica reads tolerate the documented five-second staleness bound. |
| Tenant cross-access attempt | The tenant identifier is validated at the API layer and enforced via row-level security in PostgreSQL. Dedicated customer master keys isolate cryptographic envelopes per tenant, and policy engines reject cross-tenant principals with automated integration tests verifying isolation on each deploy. |
| Insider exfiltration via bulk read | Per-principal rate limits restrict volume to 100 reads per minute by default, with additional tenant and cluster budgets protecting KMS and the audit pipeline. Real-time anomaly detection flags abnormal retrieval patterns on the audit stream, while emergency break-glass procedures mandate two-person approval and one-hour maximum token lifetimes. |
| Customer master key compromise | HSM root keys are physically non-exportable. Compromised key versions are immediately disabled, triggering a background job to re-wrap all data encryption keys under a newly generated key version alongside automated secret rotation runbooks. |
| Audit log tampering | Audit records stream to Kafka and persist in ClickHouse using Write-Once-Read-Many (WORM) storage tiers with cryptographic hash chaining per partition. A segregated security account governs the audit pipeline with separate credentials. |
Additional Considerations
Relationship to Auth System (OAuth & SSO)
An Auth System (OAuth & SSO) authenticates human operators and issues workload OIDC tokens, whereas a Secrets Manager & KMS stores and delivers credentials to authenticated workloads. Workloads authenticate using IAM roles, SPIFFE mutual TLS, or OIDC tokens issued by the identity provider rather than static stored passwords. The secrets manager trusts token issuers, and the policy engine maps token claims directly to secret path access rules.
TLS Certificate Storage
Store certificates and private keys as a unified payload protected by envelope encryption. The system monitors certificate lifecycles to trigger alerts at 30, 14, and 7 days prior to expiration. Integrations with automated ACME certificate authorities can trigger automated renewal workflows that persist new versions through standard rotation grace periods. Private key plaintexts are never logged in audit metadata.
SDK and Sidecar Ingestion Pattern
Microservices should avoid calling the central secrets API on every incoming request. Sidecar agents fetch credentials at container initialization, subscribe to version updates, and inject secrets directly into memory or local filesystems. This sidecar pattern compresses 50K application requests per second down to approximately 100 API queries per second against the centralized cluster.
Interview Walkthrough
- 25-minute interview pacing:
Skip internal hardware cryptographic accelerator details unless targeting staff-level evaluation.
- 5 minutes: Envelope encryption architecture, illustrating how customer master keys wrap data encryption keys within the hardware security module.
- 6 minutes: Static secret versioning compared against ephemeral dynamic credentials issued with lease timers.
- 5 minutes: Automated rotation workflows covering version state transitions (pending, current, deprecated, disabled) and smoke test gates.
- 5 minutes: Scaling the read path to 50K reads per second using horizontal replicas and Redis DEK caches while mitigating HSM latency.
- 4 minutes: Audit pipeline guarantees, streaming all access attempts to Kafka and immutable ClickHouse storage with Distributed Tracing.
- Start with the envelope encryption flow: data encryption keys protect payloads, customer master keys in the HSM wrap data encryption keys, and plaintext keys never persist to disk.
- Distinguish static secrets from dynamic credentials: use static versioning for third-party API tokens and dynamic short-lived leases for database access.
- Automated rotation: maintain versioned records with overlapping grace periods and enforce validation smoke tests before advancing the CURRENT pointer.
- Scale to 50K reads per second: deploy horizontal read replicas paired with short-lived Redis DEK caches to prevent hardware security modules from becoming latency bottlenecks.
- Every access audited: stream all events, including access denials, asynchronously to Kafka while embedding distributed trace context.
- Multi-tenant isolation: enforce tenant boundaries at the API layer, database row level, blob path, and KMS key policy tiers, returning HTTP 403 on cross-tenant probes.
- Break-glass access: implement dual human authorization, short time-to-live tokens, and elevated alerting without bypassing audit logs.
- Common interview pitfall: attempting to encrypt all secrets directly with a single global master key or invalidating older credentials abruptly without a grace window.
Engineering Trade-offs
Envelope Encryption vs Direct CMK Encryption
Directly encrypting every secret with a customer master key requires synchronous HSM invocations on every read operation, which is prohibitively slow and expensive at 50K reads per second. Envelope encryption performs local AES-GCM operations with per-version data encryption keys, invoking the HSM only to unwrap keys. Furthermore, customer master key rotation simply re-wraps data encryption keys without decrypting the underlying secret data at scale.
Static vs Dynamic Secrets
Static secrets are simple to store and retrieve but require manual or scheduled credential updates. Dynamic secrets eliminate long-lived passwords by generating short-lived roles on demand, though they require direct connectivity to target database clusters and background revocation daemons. Dynamic credentials shrink the blast radius of a credential leak from an indefinite exposure to a single hour-long window.
DEK Cache: Performance vs Security
Caching decrypted data encryption keys in Redis reduces KMS load by roughly tenfold but expands exposure if the cache layer is compromised. Mitigations include encrypting the cached DEK value before storing it, enforcing short 60-second time-to-live intervals, requiring mutual TLS on Redis connections, scoping cache keys by tenant and secret version, and refusing to cache high-risk master keys. The cache encryption key is loaded into protected service memory and rotated independently of the customer master keys.
Rotation Grace Period Duration
A short grace period (such as one hour) accelerates credential invalidation but increases the risk of breaking workloads that fail to refresh promptly. A longer grace period (such as 48 to 72 hours) provides safer operational transitions at the cost of a wider exposure window. Standard practice uses a 24 to 48 hour window with clients polling every five minutes.
Shared vs Dedicated HSM per Tenant
A shared multi-tenant hardware security module cluster offers cost efficiency and strong logical isolation through cryptographic policies. Dedicated hardware partitions satisfy stringent compliance regimes, such as PCI DSS or FedRAMP High, at significantly higher infrastructure cost and operational complexity.
Fail-Open vs Fail-Closed on KMS Outage
Failing open by serving from cache indefinitely preserves workload availability but risks serving revoked credentials. Failing closed during KMS outages protects security at the risk of causing widespread service outages. A pragmatic hybrid fails closed on write operations and break-glass requests, while serving reads from local caches only within a strictly bounded TTL. Once that TTL expires, the service fails closed until KMS recovers.
Review
How helpful was this walkthrough?
Click a star to rate. We actively use this feedback to refine and update our system design content.
Discussion
Share your thoughts, ask questions, or help others.