Security in System Design
The security decisions an interviewer expects you to raise unprompted: how users authenticate, how services trust each other, where secrets live, and what a breach costs you.
Covers: Authentication vs authorisation, sessions vs JWT, OAuth2 and OIDC, encryption in transit and at rest, secrets, defence in depth
Security rarely gets its own interview, but it gets mentioned in every one - and candidates who raise it before being asked stand out. You do not need to be a specialist. You need to make the standard decisions correctly and know what each one protects against.
30-second answer
Server-side sessions store state in Redis and hand the client an opaque ID: revocation is instant because you delete the record, at the cost of a lookup per request. JWTs are self-contained and signed, so any service can verify them without a lookup - but that same property means you cannot revoke one before it expires. The standard resolution is short-lived access tokens of 5–15 minutes paired with a long-lived refresh token that is stored server-side and therefore revocable. That gives you stateless verification on the hot path and a real logout.
| Server-side session | JWT | |
|---|---|---|
| Storage | Redis or database | Client-side only |
| Verification | Lookup per request | Signature check, no I/O |
| Revocation | Instant - delete the record | Not possible until expiry |
| Scales to many services | Needs a shared session store | Any service can verify independently |
| Size | Small opaque ID | Hundreds of bytes to a few KB on every request |
| Contains claims | No - look them up | Yes, but they are a snapshot at issue time |
// Access token: 15 minutes, verified statelessly by any service.
{
"sub": "user_4711",
"iss": "https://auth.example.com",
"aud": "api.example.com",
"exp": 1785062400,
"iat": 1785061500,
"jti": "01J8ZK9V...", // enables a denylist for emergencies
"scope": "orders:read orders:write",
"sid": "sess_88f2" // links back to the revocable session
}
// Refresh token: opaque, stored server-side, rotated on every use.
// Logout deletes the refresh token; the access token expires within 15 minutes.
// Worst case exposure is therefore bounded by the access-token lifetime.- Rotate refresh tokens on use and detect reuse: if an already-used refresh token appears again, it was stolen - revoke the entire family and force re-authentication.
- Store tokens in `HttpOnly`, `Secure`, `SameSite=Lax` cookies rather than
localStorage, which any XSS can read. - Always validate `iss`, `aud` and `exp`, and never accept
alg: none- historically a real and exploited vulnerability. - Keep claims minimal. A JWT is a snapshot: if you embed roles and the user is demoted, the old roles remain valid until expiry.
OAuth2 and OIDC in one paragraph
OAuth2 is authorisation delegation: it lets an application act on a user's behalf against another service without seeing their password. OIDC is an identity layer on top of OAuth2: it adds an ID token that says who the user is. 'Sign in with Google' is OIDC; 'let this app read your Google Drive' is OAuth2. Use authorisation code flow with PKCE for web and mobile - the implicit flow is deprecated - and client credentials flow for service-to-service.
Service-to-service trust
| Approach | Strength | Note |
|---|---|---|
| Network trust only ('we're in the VPC') | Weak | One compromised service and the whole network is open |
| Shared API keys | Medium | Hard to rotate, easy to leak into logs |
| mTLS | Strong | Both sides present certificates; a service mesh automates issuance and rotation |
| Signed service tokens (SPIFFE-style) | Strong | Short-lived, workload-scoped identity |
Say these points
- Sessions revoke instantly but need a lookup; JWTs verify statelessly but cannot be revoked.
- Short access tokens plus revocable refresh tokens is the standard resolution.
- Rotate refresh tokens and treat reuse as theft.
- HttpOnly Secure SameSite cookies, never localStorage.
- Zero trust: the network grants no authority; use mTLS and short-lived identities.
Avoid these mistakes
- 24-hour JWTs with no revocation story.
- Storing tokens in localStorage where XSS can read them.
- Accepting `alg: none` or failing to validate `aud` and `iss`.
- Trusting a caller because it is inside the VPC.
- Embedding roles in a long-lived token and assuming they stay current.
Expect these follow-ups
- A refresh token is stolen. How do you detect it and what do you do?
- How do you revoke a JWT immediately in a genuine emergency?
- How would you authenticate a mobile app that must work offline briefly?
30-second answer
Encrypt in transit with TLS 1.3 everywhere including internal traffic, and at rest with per-tenant or per-field keys managed by a KMS using envelope encryption - a data key encrypts the data, and the KMS master key encrypts the data key, so rotation re-encrypts keys rather than terabytes of data. Secrets belong in a managed secret store with short-lived dynamic credentials wherever possible, never in source control, container images or plain environment variables. For particularly sensitive fields, application-level encryption means a database compromise alone does not reveal the data.
Envelope encryption
1 · Generate a data key
Ask the KMS for a data encryption key. It returns both the plaintext key and a copy encrypted under the master key.2 · Encrypt locally
Encrypt the payload with the plaintext data key, then discard the plaintext key from memory. Bulk encryption never touches the KMS, so throughput is not bounded by it.3 · Store the encrypted data key alongside the ciphertext
The encrypted data key is meaningless without the master key, so it can be stored right next to the data.4 · Rotate cheaply
Rotating the master key means re-encrypting the small data keys, not the terabytes of data. This is the entire reason the pattern exists.
| Layer | What it protects against | Typical control |
|---|---|---|
| TLS in transit | Network interception, MITM | TLS 1.3, HSTS, certificate pinning where sensible |
| mTLS internal | Lateral movement after a compromise | Service mesh or SPIFFE identities |
| Disk / volume encryption | Stolen or improperly disposed hardware | Provider-managed, effectively free |
| Database TDE | Someone copying the data files | Does not protect against a compromised application |
| Application-level field encryption | A compromised database | Envelope encryption per field or per tenant |
| Tokenisation | Storing sensitive values at all | Replace card numbers with tokens held by a payment provider |
Secrets
| Approach | Verdict |
|---|---|
| Hard-coded in source | Never - it is in git history forever |
Committed .env files | Never - the most common real-world leak |
| Baked into container images | No - images get shared, cached and published |
| Environment variables from a secret store at startup | Acceptable, but visible in /proc and crash dumps |
| Fetched at runtime from a secret manager | Good - supports rotation without redeploy |
| Short-lived dynamic credentials | Best - the store issues a database credential valid for one hour |
Defence in depth, applied to a concrete threat
Take SQL injection. Prevent with parameterised queries and an ORM. Limit with a least-privilege database user that cannot drop tables or read other schemas. Detect with query anomaly monitoring and alerts on unusual result-set sizes. Contain with application-level encryption so exfiltrated rows are ciphertext, and per-tenant keys so one compromise does not expose everyone. No single control is sufficient; the layering is the design.
- Validate input at the boundary, and encode output for the context it lands in - SQL, HTML, shell, JSON each have different escaping rules.
- Least privilege everywhere - database users, IAM roles, service scopes. The application does not need
DROP TABLE. - Rate limit authentication endpoints separately and aggressively; credential stuffing is the most common real attack.
- Log security events - logins, permission changes, data exports - separately and immutably, so an attacker cannot erase their trail.
- Do not log secrets or personal data. Log aggregation systems are frequently the least protected store in the company.
Say these points
- TLS 1.3 in transit including internal calls; mTLS between services.
- Envelope encryption makes key rotation cheap - rotate keys, not terabytes.
- Disk and TDE encryption protect against stolen media, not a compromised application.
- Secrets in a manager with short-lived dynamic credentials; design for rotation from day one.
- Defence in depth: prevent, limit, detect, contain - no single control is enough.
Avoid these mistakes
- Secrets in source control or container images.
- Believing disk encryption protects against application-level compromise.
- No rotation path, so keys live forever.
- Logging tokens, passwords or personal data into a poorly protected log store.
- One database user with full privileges shared by every service.
Expect these follow-ups
- A database backup leaks. What is exposed under each encryption strategy?
- How do you rotate a signing key without invalidating every live token?
- How would you implement per-tenant encryption keys in a multi-tenant SaaS?
Showing 2 of 2 questions for security-in-system-design.
Check your understanding
4 questions · no sign-up, nothing stored
Hands-on challenge
Build it - this is what you talk about in a deep-dive round.
Write the security design for a multi-tenant SaaS
Produce the security section of a design document for a B2B product holding customer financial records.
Requirements
- Specify the authentication flow, token lifetimes and the logout/revocation path.
- Define the service-to-service trust model and how identities are issued and rotated.
- Design encryption at rest with per-tenant keys, including the envelope-encryption flow and rotation.
- Specify secret storage and how a database credential is issued, used and expired.
- For one concrete threat, list controls at all four layers: prevent, limit, detect, contain.
Stretch goals
- Design tenant isolation so a bug cannot return one tenant's rows to another.
- Write the incident response for a leaked refresh token, with detection and containment steps.