skip to content

A solution architecture must satisfy a security NFR such as 'all sensitive data encrypted at rest and in transit, with defense in depth against a compromised application server.' What architectural decisions does this drive, and what does it cost elsewhere in the design?

level: seniorimportance: should knowfreq 60%

answer

  1. encrypt in transit = TLS everywhere, not just the edge
  2. encrypt at rest = primary DB + backups + caches + indexes, all of them
  3. defense in depth = assume the app server IS compromised, limit blast radius
  4. least-privilege creds + secrets manager, not baked-in secrets
  5. cost: latency, unqueryable encrypted fields, key-rotation ops burden

basics

~20 s

It means encrypting data both while stored (at rest) and while moving over the network (in transit, e.g. TLS), and not relying on just one layer of defense — network segmentation, least-privilege access, and secrets management so that if one layer (like the app server) is breached, the attacker still can't reach everything. The cost is extra latency, operational complexity, and key-management overhead.

solid answer

~60 s

Encryption in transit means TLS everywhere data crosses a network boundary, including internal service-to-service calls, not just the public edge. Encryption at rest means the datastore (and backups, and any derived caches) encrypts data on disk, typically via a managed key-management service, with keys rotated and access to them itself audited and least-privilege. 'Defense in depth against a compromised app server' means architecting so a breach of that one layer doesn't grant the attacker everything: network segmentation so the app tier can't directly reach the database's raw storage or an internal admin network, secrets pulled at runtime from a secrets manager (not baked into config or environment in plaintext long-term), and the app server's database credentials scoped to least privilege rather than a superuser account. The cost shows up as added latency (TLS handshake overhead, especially for many internal hops), operational complexity (key rotation, cert management, secrets-manager integration), and sometimes real performance cost from field-level encryption on frequently-queried columns, which can also break the ability to index or query on that data directly.

go deeper

for a junior

Should know the basic distinction between encryption in transit (TLS) and at rest, and that both are generally expected for sensitive data.

for a middle

Should recognize that internal service-to-service traffic needs encryption too, not just the public-facing edge, and know that database credentials should be scoped rather than shared/broad.

for a senior

Should design concrete defense-in-depth layering for a 'compromised app server' threat model — network segmentation, least-privilege credentials, secrets management — and be able to name the real performance/operational costs those controls introduce.

for a principal

Should be able to weigh security NFRs against other NFRs (latency, cost, query flexibility) at a system-wide level, decide where field-level encryption or a service mesh is actually warranted versus overkill, and design the operational model so security controls remain maintainable at scale rather than becoming their own outage risk.

## An absolute rather than a budget Security NFRs differ from most other non-functional requirements in that they're often expressed as an absolute ('all sensitive data must be encrypted') rather than a percentile or budget, but translating them into architecture still requires the same discipline: - identifying the concrete **mechanisms**; - the **layers** they apply to; - and the **cost paid elsewhere** in the system. ## Encryption in transit Encryption in transit means every network hop carrying sensitive data uses TLS (or an equivalent transport-layer encryption), and the common architectural mistake is stopping at the public edge — terminating TLS at a load balancer or API gateway and then running plaintext HTTP between internal services 'because it's a private network.' A defense-in-depth security posture treats the internal network as untrusted too, because internal networks get compromised more often than architects assume when the NFR was written casually. The mechanism for doing this properly at scale is usually a service mesh or sidecar proxy pattern that automatically wraps service-to-service calls in mutual TLS (mTLS) without every service team hand-rolling certificate handling, because manual TLS setup per service is exactly the kind of thing that gets skipped under deadline pressure. ## Encryption at rest Encryption at rest means data is encrypted on physical/logical storage — database volumes, backups, object storage, and any derived caches or search indexes that might also hold a copy of sensitive fields. The mechanism is typically delegated to a managed key-management service (KMS): the storage layer encrypts with a data key, that data key is itself encrypted (enveloped) by a master key held in the KMS, and the KMS enforces access control and audit logging on who/what can request key material. This matters architecturally because 'encryption at rest' is trivially satisfiable at the top-level datastore but easy to miss in secondary copies — a nightly backup, a data warehouse ETL pipeline, or a search index built from the same records — each of which needs the same guarantee independently, and a security review that only checks the primary database misses these. ## Assume the app server is already compromised 'Defense in depth against a compromised application server' is the mechanism that most directly shapes the architecture beyond just 'turn on encryption,' because it assumes a specific breach scenario — an attacker gaining code execution on an app instance — and asks what they can reach from there. The architectural response layers several independent controls so no single one being defeated (which is the working assumption) gives full access: - **network segmentation** so the app tier's security group/firewall rules can reach only the specific database port and no lateral access to other internal systems; - **database credentials scoped to least privilege** (the app's service account can read/write the tables it needs, not administer the database or read unrelated tenants' data); - **secrets fetched at runtime** from a secrets manager rather than stored in environment variables or config files that persist in the compromised instance's filesystem or process memory indefinitely; - and, for the most sensitive fields, **application-level (field-level) encryption** so that even a compromised app server with valid database credentials only retrieves ciphertext for the most critical fields unless it also has the specific decryption key, which can be scoped even more narrowly than general DB access. ## Blast radius, rather than a checkbox Why this exists as an architectural discipline rather than a checkbox: security NFRs are stated as absolutes because a partial implementation (encrypt the primary DB but not backups; TLS at the edge but not internally; broad database credentials with encryption bolted on top) provides much less real protection than the stated requirement implies, while looking compliant on a surface-level audit. The 'compromised app server' framing specifically forces architects to think in terms of blast radius rather than perimeter — assuming the perimeter will eventually be breached and designing so that breach doesn't cascade into full data exposure. ## What it costs elsewhere The costs are concrete and worth naming honestly rather than treating security as free. - **TLS everywhere**, including internal mesh traffic, adds real latency from handshake overhead and CPU cost from encryption/decryption, which matters when internal call chains are already latency-budgeted tightly. - **Field-level encryption** on frequently-queried columns can make those columns unindexable or unqueryable in their encrypted form, forcing either application-side filtering (worse performance) or accepting that field can't be efficiently searched at all, sometimes requiring a redesign of the query pattern. - **Key rotation and secrets-manager integration** add operational surface area and a new class of outage risk (an app that can't fetch a secret at startup fails to boot), which needs its own resilience design (caching secrets with a sane TTL, graceful degradation). - **Least-privilege credential scoping**, done thoroughly, means many more distinct service accounts and roles to provision and maintain rather than one shared broad-access account, which is genuinely more operational work. ## How it fails in production Failure modes in production include: 1. TLS terminated at the edge with plaintext internal hops, discovered only during a security audit or, worse, after a lateral-movement incident. 2. Encrypted primary databases with an unencrypted nightly backup or an unencrypted downstream analytics copy of the same data. 3. Overly broad database credentials on the app server meaning a code-execution compromise immediately grants full data access regardless of how well encryption was implemented elsewhere. 4. Secrets baked into container images or long-lived environment variables that persist in the compromised instance far longer than a short-lived, rotated credential would. ## A worked example on a healthcare records API A worked example: a healthcare records API satisfies its security NFR with mTLS between all internal services via a service mesh, KMS-backed encryption at rest on the primary database and its backups, field-level encryption specifically on the most sensitive clinical-notes column (accepting that column can no longer be full-text searched, and building a separate, access-controlled search index instead), a database service account scoped to only the tables the API needs with no administrative rights, and secrets fetched at boot from a secrets manager with a short-lived cache and automatic rotation — accepting the added internal mTLS overhead per hop and the operational cost of managing the additional service accounts and key rotation schedule as the deliberate price of the defense-in-depth requirement.

  • Why is encrypting only the primary database not sufficient to satisfy an 'all sensitive data encrypted at rest' NFR?
    Because sensitive data typically exists in more than one place — nightly backups, data-warehouse or analytics copies, search indexes, and caches can all hold the same fields, and each of these needs its own independent encryption guarantee. A security review that checks only the primary datastore will miss these secondary copies, which are common real-world sources of data exposure.
  • What does 'defense in depth against a compromised application server' specifically ask the architect to assume, and how does that assumption change the design compared to just having a firewall at the network perimeter?
    It asks the architect to assume the perimeter has already been breached — that an attacker has code execution on an app instance — and to design so that this alone doesn't grant full data access. That shifts the design from perimeter-only controls to layered ones: least-privilege database credentials, network segmentation limiting what the app tier can reach, and secrets fetched at runtime rather than stored locally, so a single breached layer has a bounded blast radius.
  • What's a concrete performance or functionality cost of applying field-level encryption to a frequently-queried database column?
    The encrypted value generally can't be used directly in a database index or a WHERE-clause filter the way plaintext can, since equivalent values encrypt to different ciphertext with proper encryption. This typically forces either moving that filtering logic into the application (fetching more rows and filtering after decryption, which is slower) or building a separate, deliberately access-controlled index for that field.

Like a bank vault built inside a building that also has locked offices, badge-restricted floors, and a safe within the vault for the most valuable items — if a thief gets past the front door (the compromised app server), they still hit a locked office, then a vault, then a safe, so getting past one layer doesn't hand them everything.

saying these in an interview costs you the question

  • Treats encryption at rest as satisfied once the primary database is encrypted, without checking backups/caches/indexes
  • Terminates TLS only at the public edge and assumes internal network traffic is safe by default
  • Gives the application server's database credentials broad or administrative access 'for simplicity'
  • Stores secrets in plaintext environment variables or baked into a container image with no rotation
  • Treats 'defense in depth' as a synonym for 'more firewalls' without addressing credential scope or blast radius
  • Never acknowledges any cost (latency, queryability, operational burden) from the security controls proposed

context