10 Netflix Php Developer Interview Questions & Answers

netflix icon

Questions with Detailed ExplanationsWith Detailed Explanations

(Last Updated: August 28, 2026)

1. Define the API for fetching a deduplicated streaming-homepage viewport.API DesignMediumNetflix

Question Details

Define the client-facing API for fetching rows and titles for the initial and subsequent streaming-homepage viewports while preventing duplicate titles across visible modules. Cover request context, cursor-based pagination, row and title identifiers, deduplication state, ranking metadata, partial responses, caching, retries, errors, backward compatibility, and client synchronization.

Short Interview Answer (30-60 seconds)

At a high level, I would design one stateless homepage API that returns the first or next viewport, with rows, titles, ranking hints, and an opaque nextCursor. The client sends JWT auth, request context, and its dedup state, so the server can filter repeated titles before building the response. The API also returns dedupStateDelta so the client can sync its local state for the next call. The main trade-off is that we keep the server simple and scalable, but the client and response format become richer.

Detailed Explanation

This question asks for a simple way to load the home screen of a streaming app. The first screen and later screens should show rows and titles without repeating the same title twice. The app also needs a way to remember what it already showed, so the next screen can continue cleanly. The diagram gives the exact flow, from the client request to ranking, catalog lookup, cache, and the final response. The answer must explain the first load and the next load in the same way, so the client never sees repeated titles.

Useful Questions to Ask the Interviewer
  • Should deduplication be per session, per profile, or per device?
  • How long should the client keep dedup state?
  • Do we prefer fresher ranking or stronger cache reuse?
  • Should the API return partial rows when one backend is slow?
Define the API for fetching a deduplicated streaming-homepage viewport. diagram
How to Explain It in an Interview
1. Goal and API boundary

At a high level, the goal is to fetch one deduplicated homepage viewport. The client asks for the first screen, then asks for the next screen with a cursor. The API is stateless, so the server does not keep the whole viewport between calls. The client sends back dedup state, and the server uses it to avoid repeated titles. That keeps the design simple to scale and easy to retry.

2. Request shape and context

The request uses GET /v1/home/viewport. The diagram shows Authorization: Bearer <JWT>, X-Request-ID, X-Client-Version, and optional If-None-Match. The query context includes region, device type, profile, language, viewport height, row limit, title limit per row, cursor, dedup state, and experiment flags. I would explain them as plain screen-shaping inputs. Cursor means next page. Dedup state means which title IDs were already shown. The home:read scope limits what the token may read.

3. Server flow

The request first reaches AuthN / AuthZ. The API checks the JWT, then checks whether this user can read this profile. Next is request validation for required fields, limits, cursor format, and dedup state format. Then Context Builder creates the user context. Candidate Fetcher asks the ranking service for ranked candidates. The ranking service returns ranked title IDs and scores for the user context. The Content Catalog returns title metadata, availability, images, and maturity. Cache (Redis) can answer popular viewport or metadata lookups faster. Dedup Engine removes title IDs that the client already showed. Row Assembler builds the final rows and next cursor. Response Shaper turns that into JSON and adds caching headers.

4. Response and synchronization

The response is 200 OK (JSON). It includes rows[], titles[], ranking metadata, pagination.nextCursor, dedupStateDelta, and meta.cache. rows[] is the ordered list of modules. rowId stays stable for UI diffing. titles[] is the filtered list after deduplication. Ranking metadata includes rank, score, reason, badges, and other decision hints. dedupStateDelta tells the client which title IDs to merge into local state before the next call. That is how later viewports stay in sync without making the server stateful.

5. Errors, partial responses, and trade-offs

The diagram shows 400, 401, 403, 429, 503, and 5xx. 400 means invalid input. 401 means missing or invalid token. 403 means authenticated but not allowed. 429 means too many requests. 503 means temporarily unavailable. The response can include error.code, message, and retryAfter. Partial responses are allowed, with warnings[] in meta. The caching key includes user, profile, region, device, language, experiment, viewport size, cursor, and dedup state version. Short TTL and stale-while-revalidate make the page fast. The trade-off is clear: better dedup and freshness need more client state and a richer response shape.

Practical Complexity & Trade-offs

This design keeps the server stateless for viewport loading, which helps scaling and retries. The client sends cursor and dedup state, so the server can remove repeated titles without storing all session memory. That is safer for growth, but it makes the response and client logic more complex. The API also uses ranking, catalog lookups, and Redis caching, which makes the page faster. The downside is more moving parts. Error handling is also important. The API must return clear codes like 400, 401, 403, 429, and 503. Partial responses are useful because the user still sees some content when one part fails. The trade-off is freshness versus cache speed, and simplicity versus dedup correctness.

Why Interviewers Ask This

Interviewers want to see whether I can design a clear API boundary and keep client state aligned with server behavior. They are checking request modeling, cursor pagination, response shaping, deduplication logic, cache use, and failure handling. They also want to see that I can separate authentication from authorization, explain retries and partial responses, and talk about trade-offs in simple words. Most of all, they are testing whether I can turn a product requirement into a practical API that is clear, scalable, and easy for clients to use.

Interviewer may ask next
How would you change the API if the client can be offline and sync later?

I would keep the same viewport API shape, but I would make the dedup state more durable on the client. The affected flow is the request and the dedupStateDelta response. The client would store the last known state locally and send it when it comes back online. The server would still validate the cursor, request context, and dedup rules before returning rows, so the result stays correct. The JWT check and profile authorization would stay exactly the same, because offline sync should not weaken access control. The main downside is that offline clients can drift from the newest ranking or catalog data, so they may need a refresh or a smaller maxAge window when they reconnect. That gives better continuity, but less freshness, and a little more client logic overall.

How would you support faster responses for repeated home viewport loads without showing stale data too long?

I would keep Redis caching and the meta.cache hints, but I would use a short TTL and stale-while-revalidate behavior. The affected flow is the Cache (Redis) lookup before ranking and catalog calls. This still keeps the API correct because request validation, dedup filtering, and cursor checks happen on every request. The cache only speeds up popular viewports and metadata, and the response can still tell the client whether the data was fresh or reused. I would also keep the cache key tied to user, profile, region, device, language, experiment, viewport size, cursor, and dedup state version, so one user never sees another user’s result. The downside is more cache complexity, and some responses may be slightly stale until refresh finishes. That is a fair trade-off for a read-heavy homepage where speed matters a lot, especially on the first screen.

2. Define the APIs for real-time ad frequency checking and impression recording.API DesignHardNetflix

Question Details

Define the API contracts for the two distinct workloads in an ad frequency-capping system: a latency-critical operation that checks whether an ad may be shown before serving, and an operation that records an impression after it is shown. Cover resources, request and response fields, cap scopes and windows, idempotency, concurrency, duplicate events, errors, timeouts, consistency, and versioning.

Short Interview Answer (30-60 seconds)

At a high level, my goal is to keep ad serving fast and keep cap counts correct. I would split the design into a real-time check API and an async impression record API. The check path uses HTTPS, mTLS, and JWT auth to read counters from a low-latency store and return allow or deny quickly. The record path accepts the impression, dedupes by eventId, updates counters, and feeds analytics later. The main trade-off is speed on the check path versus eventual consistency for reporting.

Detailed Explanation

This question asks how to design two APIs for ad frequency capping. One API runs before the ad is shown. It decides if the ad may be served. The second API runs after the ad is shown. It records the impression so future checks stay accurate. The main challenge is that the first call must be very fast, and the second call must be safe against duplicates. I will follow the diagram and explain the check path, the async record path, security, counters, errors, and trade-offs.

Useful Questions to Ask the Interviewer
  • Which cap scopes should we support first: user, IP, device, or user+campaign?
Define the APIs for real-time ad frequency checking and impression recording. diagram
How to Explain It in an Interview
1. Start with the goal and boundary

I separate this design into two paths. The first path is the real-time check before ad serving. The second path is the impression record after the ad is shown. The client in the diagram is the ad decision service. The boundary keeps the hot path small. That matters because the check API has a 50 ms p95 target.

2. Explain the check API

The check API is POST /v1/frequency/check. It sends requestId, userId, adId, campaignId, scope, cap, and now. The scope can be user, ip, device, or user+campaign. The diagram also shows scope.additional for custom combinations. The cap windows use ISO-8601 durations such as P1H, P1D, P7D, P30D, and P1M. The response is 200 OK with allowed, remaining, resetAt, currentCount, decisionId, and ttlSeconds. The service reads the counter from the low-latency store and returns one clear yes-or-no answer.

3. Explain the impression record API

The record API is POST /v1/impressions. It sends eventId, userId, adId, campaignId, scope, additional, timestamp, source, and metadata. The diagram treats eventId as the idempotency key, so the same event should not count twice. The response is 202 Accepted, because the system only acknowledges the write quickly and processes the event async. The event then goes to the event ingestion service, which validates the request, checks duplicates, persists the event, updates counters, and publishes the event for analytics. The trade-off is that reporting is not fully synchronous, but the serving path stays fast.

4. Explain identity, security, and authorization

The diagram shows HTTPS, TLS 1.2+, and mTLS preferred. mTLS means both sides verify each other with certificates. The auth box also shows OAuth2 client credentials or JWT. I would say the token proves who the caller is, and the scope proves what it may do. The JWT carries claims like iss, sub, exp, and scopes. The receiving service still owns authorization, so a valid token is not enough by itself. The key scopes are ad.check and ad.record. If the token is missing or expired, the API returns 401. If the token is valid but the scope is missing, it returns 403.

5. Explain counters, consistency, and duplicates

The frequency cap service owns the decision logic. It reads and writes counters in a low-latency store such as Redis or KeyDB. The key format is based on scope, ad id, and window start, like {scope}:{adId}:{windowStart}. The value tracks count, expiresAt, and lastEventId. The check API needs a strong read from that store. The record API can accept the event first, then update the counter and analytics later. That is why the diagram shows a durable event store or data lake, such as Kafka, S3, or ClickHouse, with eventual consistency. Duplicate events do not increase the count twice because the record path dedupes by eventId.

6. Cover errors, limits, versioning, and observability

The diagram shows 400 for bad input, 401 for invalid or expired token, 403 for missing scope, 409 for duplicate event handling, 429 for rate limits, and 503 for temporary service failure. It also shows Retry-After on rate limiting. The check API target is about 500 req/s per client, and the record API target is about 2000 req/s per client. Versioning stays in the URL as /v1/..., and backward-compatible additions are safe. I would end by mentioning correlation IDs, metrics, and tracing.

Practical Complexity & Trade-offs

The benefit of this design is that ad serving stays fast, because the check API uses a small real-time store and returns a simple allow-or-deny answer. The downside is that reporting is not instantly complete, because impression data moves through an async path. This is safer for duplicates, because eventId and idempotency stop double counting, but it adds more moving parts. We accept that trade-off because the check path needs very low latency, while analytics can tolerate eventual consistency. Versioning in /v1/... also helps us add new fields later without breaking old clients. The cost is extra operational work for the ingestion service and the store.

Why Interviewers Ask This

Interviewers ask this to see whether I can design clear API boundaries and model requests and responses correctly. They also want to know if I understand fast decision paths, idempotency, duplicate handling, authentication, authorization, and error behavior. Another goal is to see if I can explain trade-offs in simple words, especially the tension between low latency for ad checks and eventual consistency for impression reporting.

Interviewer may ask next
How would you change the design if the check API started timing out during peak traffic?

I would keep the same endpoints, but I would make the check path smaller and more cache-driven. The affected flow is POST /v1/frequency/check through the frequency cap service and the low-latency store. I would keep request validation, token checks, and scope checks in place, but I would avoid extra work on the hot path. I would also use short TTLs and a clear fail-closed rule if the store cannot return a trustworthy answer. The main safety rule is that the service must still use the current counter state and must not invent a decision. The downside is that a stronger cache strategy can hide fresh updates for a short time, so the risk becomes stale reads during peak load and slightly less accurate caps for some users overall and across devices.

How would you handle duplicate impression events from retrying clients?

I would keep POST /v1/impressions the same and use eventId as the idempotency key everywhere the event is handled. The affected flow is the record impression path through the event ingestion service, the counter store, and the analytics pipeline. If the same event arrives again, the service should not increase the counter twice, and it can return the duplicate-safe accepted result shown in the diagram. I would keep the async publish step because it protects serving latency. The main downside is more storage and lookup work for deduplication, plus the chance that analytics lags behind the serving decision for a short time. That is still the right trade-off for accuracy and safety, especially when retries happen during network hiccups or service restarts in production, at scale across regions and clients.

3. Define the APIs for campaign pacing, budget updates, and serving eligibility.API DesignHardNetflix

Question Details

Define APIs for an ad pacing platform that lets advertisers create and update campaigns, budgets, flight dates, targeting constraints, and delivery goals while allowing serving nodes to obtain low-latency campaign eligibility and pacing decisions. Cover nested budget scopes, optimistic concurrency, idempotency, propagation of mid-flight changes, event reporting, errors, authorization, and compatibility.

Short Interview Answer (30-60 seconds)

At a high level, my goal is to let advertisers change campaigns and budgets safely, while serving nodes make a fast eligibility decision. I would keep writes in the control plane with campaign and budget APIs, and keep reads in a low-latency eligibility API backed by snapshots and an edge cache. The main security decision is JWT over HTTPS with mTLS, plus idempotency and ETag-based optimistic concurrency on updates. The trade-off is that serving stays fast, but mid-flight changes reach the edge through async propagation instead of instantly.

Detailed Explanation

This question is about one system that does two jobs. First, it lets advertisers create and update campaigns and budgets. Second, it lets serving nodes quickly decide whether an ad can run. The hard part is keeping writes safe and reads fast at the same time. The diagram shows a control plane, a propagation path, and a serving plane. That is the design I would follow. It keeps edits in one place and eligibility checks in another place.

Useful Questions to Ask the Interviewer
  • Do we need budget scopes for account, campaign, line item, and creative?
  • Should a change take effect on the next snapshot or immediately?
  • Should serving fail open or fail closed when cache data is stale?
Define the APIs for campaign pacing, budget updates, and serving eligibility. diagram
How to Explain It in an Interview
1. Start with the goal and boundary

I would start by saying the system has two main jobs. One job is to let advertisers write campaign and budget changes. The other job is to let serving nodes make a fast eligibility decision. That is why the diagram separates the control plane from the serving plane. The control plane owns create, update, activate, pause, and versioning. The serving plane owns the low-latency check. This split keeps writes safe and reads fast.

2. Explain the write APIs for campaigns and budgets

For campaigns, the base path is /v1/campaigns. The diagram shows POST, GET, PATCH, PUT, and DELETE. It also shows GET /v1/campaigns/{id}/versions. For budgets, the base path is /v1/budgets, and it shows the same main write patterns. The table also shows lookup by scope, such as GET /v1/budgets?scopeType=campaign&scopeId={id}. The request uses Authorization: Bearer <JWT>, Idempotency-Key on writes, and If-Match: <ETag> on updates. That lets the server reject duplicate writes and stale writes. The response returns JSON plus ETag, Request-Id, and success codes like 200 OK and 201 Created.

3. Cover nested budget scopes and safe updates

The budget model is nested. The example shows account, campaign, line item or ad set, and an optional creative cap. That means one change can roll up into parent limits. I would explain that the budget service owns the rule that a child cannot exceed the parent cap. The If-Match check is important here because two people may edit the same budget at once. If the ETag no longer matches, the server should reject the update instead of silently overwriting it. That protects correctness during mid-flight changes.

4. Explain the low-latency eligibility path

Serving nodes send POST /v1/eligibility with campaignId, hashed userId, and context like geo, device, and time. The eligibility service owns the final decision. It checks targeting rules, pacing, and remaining budget. The response is 200 OK with a decision and metadata such as pacing and reason. The diagram also shows a local cache and fallback path. The edge cache uses the newest snapshot when it can, and it can use the last good snapshot if needed. That is how the design keeps the eligibility path under the sub-50 ms target.

5. Explain propagation, snapshots, and event reporting

The write path does not talk directly to every serving node. It updates the authoritative store, sends change data through the event stream, builds a pacing snapshot, and publishes that snapshot to the edge cache. That is how mid-flight changes move across the system. The reporting side is separate. The ingestion API is POST /v1/events, and it is async and idempotent. It records impression, click, view complete, conversion, budget exhausted, and pacing throttled events. This supports reporting without slowing the serving decision path.

6. Close with security, errors, and versioning

The cross-cutting rules are the same across the diagram. JWT / OAuth 2.0 handles caller identity. HTTPS and mTLS protect transport. Rate limiting is per advertiser or API key. Observability uses logs, metrics, and traces. Versioning uses a vendor media type like /vnd.company.v1+json. Common failures are 400, 401, 403, 404, 409, 422, 429, and 500. The trade-off is clear: this design is more complex than one simple API, but it gives fast serving and safe writes at the same time.

Practical Complexity & Trade-offs

The benefit of this design is clear separation. Write APIs handle campaign and budget changes, while the eligibility API stays fast. Idempotency keys help the server ignore duplicate writes. ETag and If-Match help stop lost updates. The edge cache and snapshot path reduce read latency, but they also add delay before a change reaches every server. That is the main trade-off. Another benefit is simpler reporting, because events are async and do not block serving. The downside is more moving parts: store, event stream, snapshot builder, cache, and fallback logic. We accept that because ads need both safe updates and very fast eligibility checks.

Why Interviewers Ask This

Interviewers ask this to see whether I can split a hard API into clear write and read paths. They also want to know if I understand safe updates, low-latency reads, auth, idempotency, and versioning. A strong answer shows that I know which component owns each rule and what happens on stale writes, bad tokens, and rate limits. They also check whether I can explain trade-offs in simple words instead of only naming tools.

Interviewer may ask next
How would you handle a budget change that must reach serving nodes quickly during a live campaign?

I would keep the same design, but I would treat that budget update as a high-priority change on the write path. The affected endpoint is PATCH /v1/budgets/{id} or the related budget update flow. The update still uses If-Match and Idempotency-Key, so we do not lose safety. The control plane writes to the authoritative store first, then emits the change through the event stream, rebuilds the pacing snapshot, and pushes the new snapshot to the edge cache. Serving nodes keep reading the last good snapshot until the new one arrives. That keeps correctness and security in place, but the downside is more operational work and a short window of eventual consistency.

How would you make event ingestion safe if the same click or impression is sent twice?

I would keep POST /v1/events async and idempotent, and I would add a stable event id or idempotency key to the event body or header. The ingestion service would dedupe repeated events before publishing them downstream. That keeps reporting correct, because one user action is counted once even if the network retries. The observability path still gets logs, metrics, and traces, and the serving path is not slowed down. The downside is extra state for dedupe and a little more complexity in the ingestion service, but that is worth it because event traffic is noisy and retries are common.

4. Define the APIs for managing and deploying publisher configuration rules.API DesignHardNetflix

Question Details

Define APIs that allow internal operators and publisher-facing tools to create, validate, version, test, deploy, evaluate, roll back, and audit publisher-specific advertising rules. Cover inventory hierarchy, inheritance and overrides, conflict reporting, draft and active versions, safe rollout, authorization, validation errors, idempotency, and pagination.

Short Interview Answer (30-60 seconds)

At a high level, I would design this as a safe rule-management API for publisher-specific advertising rules. Internal operators and publisher tools call the Publisher Configuration API over HTTPS. The API uses mTLS, JWTs, and roles or scopes from the Auth Service. It supports inventory reads, rule CRUD, versions, validation, tests, deploy, rollback, and audit. The main trade-off is more API surface and more states, but that gives safe rollout, clear conflict checks, and easy rollback.

Detailed Explanation

This question asks how to manage publisher rules safely. These rules decide what config a publisher gets. The main goal is to let trusted users change rules without breaking live traffic. We need to keep the hierarchy, the active version, and the rollout safe. One bad edit can affect many publishers. I will explain the answer in the same order as the diagram, from login to read and write APIs, validation, testing, deploy, rollback, and audit.

Useful Questions to Ask the Interviewer
  • Are hierarchy levels exactly publisher, domain, app, and placement?
  • Should deploy support gradual rollout by percentage?
  • Do we need approval before activation?
Define the APIs for managing and deploying publisher configuration rules. diagram
How to Explain It in an Interview
1. Goal and boundary

At a high level, this API is the control plane. It manages rules, but it does not serve ads itself. The Publisher Configuration API (REST) is the main entry point. The Inventory Service owns the publisher, domain, app, placement hierarchy, and assignments. The Rule Service owns rule definitions, inheritance, overrides, and the effective config. For reads, I would use GET /inventory/publishers, GET /inventory/{publisherId}, GET /inventory/{publisherId}/properties, GET /inventory/{publisherId}/placements, and GET /inheritance/{resourceType}/{id}. Those calls help the caller see where a rule applies before changing it.

2. Identity and request flow

Clients are Internal Operators and Publisher Tools. They send HTTPS requests with mTLS and a JWT access token. The API Gateway checks mTLS, validates the JWT, applies rate limits, honors the idempotency key, and logs the request. The Auth Service checks SSO, OAuth2, or OIDC, then returns the user roles and scopes. The API uses that result for authorization. Authentication proves who the caller is. Authorization decides what that caller may do. The request then reaches the Publisher Configuration API, and the response returns back through the gateway as JSON.

3. Rule CRUD and versions

The write side starts with GET /publishers/{publisherId}/rules?cursor=..., POST /publishers/{publisherId}/rules, GET /rules/{ruleId}, PUT /rules/{ruleId}, and DELETE /rules/{ruleId}. Versioning uses GET /rules/{ruleId}/versions?cursor=..., POST /rules/{ruleId}/versions, and GET /rules/{ruleId}/versions/{versionId}. A draft is a safe copy that can change. The active version stays stable until publish. Idempotency-Key on POST, PUT, and DELETE helps retries stay safe. Cursor pagination keeps large lists small.

4. Validation and conflicts

Before a rule goes live, the API checks it. The diagram shows POST /rules/validate, POST /rules/{ruleId}/versions/{versionId}/validate, and GET /rules/{ruleId}/conflicts. The Validation and Conflict Service checks schema rules, business rules, inheritance resolution, and conflict detection. If the input is bad, the API should return a clear validation error, usually 400. If the caller lacks access, it should return 401 or 403. If the rule state changed under us, 409 is the right choice. I would keep the error body in a problem-details format so clients can fix the request quickly.

5. Test, deploy, rollback, and audit

For safe release, the API uses POST /rules/{ruleId}/test with versionId and testData in the body, GET /rules/{ruleId}/evaluations?cursor=..., and GET /rules/{ruleId}/evaluations/{evalId}. The Evaluation Service simulates the rule on test data and returns metrics and results. For rollout, the diagram shows POST /rules/{ruleId}/deploy with versionId and strategy, plus POST /rules/{ruleId}/rollback with targetVersionId. The Deployment Service owns safe rollout, traffic ramp, feature flags, activation, and rollback. Audit is separate through GET /rules/{ruleId}/audit?cursor=... and GET /rules/audit?publisherId=...&type=.... The Audit Service keeps immutable history, and its events can feed the message bus and monitoring.

6. Failures and trade-offs

If validation fails, I would stop before activation. If the version conflicts with the active state, I would return 409 and ask for a fresh read. If authorization fails, the caller should not reach the write path. The trade-off is clear: this design adds more endpoints, more states, and more checks. But it also gives safer rollout, better rollback, better auditability, and clearer ownership. For this problem, that is the right trade because one bad rule can affect many publishers.

Practical Complexity & Trade-offs

The benefit is that each service has one clear job. The Inventory Service owns the hierarchy, the Rule Service owns rule data, the Validation and Conflict Service checks correctness, the Evaluation Service tests behavior, the Deployment Service controls rollout, and the Audit Service stores history. This reduces risk, but it adds more API calls and more state to manage. Cursor pagination keeps large lists usable. Idempotency keys make retries safer. The trade-off is slower development and more operational work. We accept that cost because publisher rules are high impact, and safe rollback matters more than a tiny API surface in practice.

Why Interviewers Ask This

Interviewers ask this to see whether I can turn a business need into a safe API design. They want to know if I can model hierarchy, drafts, versions, validation, rollout, rollback, and audit without mixing responsibilities. They also check whether I understand authentication, authorization, idempotency, pagination, and clear failure handling. Good answers show judgment, because they explain why the design is safe, practical, and easy to operate.

Interviewer may ask next
How would you make rollout safer for only a subset of publishers?

I would keep the same deploy API, but make the strategy field more explicit for gradual rollout. POST /rules/{ruleId}/deploy would still take versionId and strategy, and the Deployment Service would ramp the change in small steps. That keeps the rule version immutable while only changing who receives it first. Correctness stays strong because we still validate the version before activation, and rollback stays available if metrics look bad. Security also stays the same because the same JWT, scopes, and mTLS checks protect the call. I would also keep the audit event for each rollout step, so operators can see what happened, when it happened, and which publisher group changed. The downside is more operational work. We need monitoring, rollout status, rollback checks, and careful control for partial releases. That adds coordination, but it gives much safer deployments.

How do you keep conflict checks and large rule lists usable as the data grows?

I would keep the same conflict and list endpoints, but rely on cursor-based pagination everywhere the diagram shows large result sets. GET /rules/{ruleId}/conflicts, GET /rules/{ruleId}/versions, GET /rules/{ruleId}/evaluations, and the audit list endpoints already fit that pattern. That keeps responses small and predictable, even when one publisher has many rules or many history items. Validation and conflict detection still happen in the Validation and Conflict Service, so we do not lose correctness. I would also return the same problem-details error format when a cursor is bad or a page is no longer valid. The downside is that clients must keep track of cursors instead of simple page numbers, and the API is a little harder to use at first. That is acceptable because the read paths stay fast and stable, and it prevents very large responses.

5. Define the APIs for backing up, listing, and restoring files.API DesignHardNetflix

Question Details

Define the API surface for a scalable file backup service. Include starting incremental or full backups, uploading content or chunks, recording metadata, inspecting job status, listing snapshots, restoring files or directories, retrying failed work, and canceling operations. Address idempotency, checksums, pagination, authorization, concurrent changes, errors, and version compatibility.

Short Interview Answer (30-60 seconds)

At a high level, I would design this as a trusted backup API that starts jobs, uploads chunks, stores metadata, and restores exact snapshots later. The main path is client → API gateway → auth service → backup service → storage, while workers handle long-running upload, verify, garbage collection, and retry tasks. The main security choice is to validate JWT, OAuth2/OIDC, API keys, and RBAC or ABAC before the backup service does work. The trade-off is stronger safety and consistency, but more moving parts and asynchronous job handling.

Detailed Explanation

This question asks me to design a safe file backup API. A client should be able to start a full or incremental backup, upload chunks, check progress, list snapshots, and restore files or folders. It also needs retry and cancel actions. The hard part is avoiding duplicate work, keeping file versions correct, and making sure only trusted callers can use it. I will explain the flow in the same order as the diagram, from the client to the gateway, auth service, backup service, storage layer, worker pool, and event bus.

Useful Questions to Ask the Interviewer
  • Do we need both full and incremental backups?
  • Should restore work for one file, many files, and whole folders?
  • How long should snapshots and failed jobs stay?
  • Do we want polling only, or polling plus event updates?
Define the APIs for backing up, listing, and restoring files. diagram
How to Explain It in an Interview
1. Goal and API boundary

At a high level, I would separate this into backup, inspection, restore, and retry APIs. The clients can be a web/admin UI, a mobile app, or a backend or CLI tool. The API Gateway keeps the edge simple with routing, rate limiting, request validation, CORS, and /v1 versioning. The Backup Service owns job control, metadata, deduplication, snapshots, retention, and restore state. Storage keeps the chunks, the file index or dedup store, and backup metadata. That split matters because the API must support large files, slow jobs, and future versioning without mixing concerns.

2. Start a backup and upload chunks

The request first starts with POST /v1/backups. The diagram shows full and incremental backup behavior around that family, and it also shows pause and cancel behavior for long jobs. The client then uploads content with POST /v1/uploads/chunks. Chunked upload is important for large files because it lets the client resume after a failure. I would explain that each chunk can carry a checksum, like Content-MD5 or SHA-256, so the service can verify integrity. The Idempotency-Key header means a retry does not create a second backup job.

3. Inspect jobs, metadata, snapshots, and versions

For read paths, the API gives job and snapshot inspection. The jobs family uses GET /v1/jobs/{jobId}, and the diagram also shows list jobs and file metadata actions in the same area. The snapshot family uses GET /v1/snapshots/{snapshotId}. That lets the client list snapshots, read snapshot details, see files in a snapshot, and inspect versions. Pagination means limit and cursor keep the response stable when the list is large. I would mention status, createdAt, updatedAt, startedAt, completedAt, progress, bytesProcessed, bytesTotal, filesProcessed, filesTotal, errors, snapshotId, and retryCount.

4. Restore files, retry failed work, and cancel jobs

Restores use POST /v1/restores. The diagram shows restore files, restore directories, get restore status, and cancel restore in that family. Retry and cancel for failed work use POST /v1/jobs/{jobId}:retry and POST /v1/jobs/{jobId}:cancel. I would explain that restores should use immutable snapshots, so the user gets a consistent point in time. ETags are version tags, and optimistic locking means the service checks the latest version before writing. The trade-off is that consistency can slow the system down, but it avoids restoring the wrong file version.

5. Security, validation, and error handling

The main security decision is to validate the caller before work starts. The diagram shows JWT, OAuth2/OIDC, API keys, and RBAC or ABAC. A JWT is a signed token with identity and claims. OAuth2/OIDC is the login and token flow. API keys are simple shared secrets for machine callers. RBAC or ABAC means role-based or attribute-based access control, which decides who may do what. I would say the gateway forwards the request, the auth service validates the token over mTLS, and it returns JWT claims or an auth result. The Backup Service then accepts the authorized request. Errors should use standard HTTP codes with problem+json details, so clients get a machine-readable error body. Versioning is simple too. Everything stays under /v1, which makes backward compatibility easier.

6. Events, notifications, and trade-offs

The backup work is asynchronous, so the Worker Pool handles upload, verify, garbage collection, and retry tasks. The Backup Service publishes progress events to the Event / Notification Bus, which the diagram labels with Kafka / SNS / SQS. From there, Email / SMS and Webhooks can receive updates. That is useful because backup jobs may run for a long time. The job status model matches this design well: PENDING, RUNNING, COMPLETED, FAILED, CANCELED, and EXPIRED. The trade-off is more moving parts, but the benefit is better scale, safer retries, clearer progress reporting, and cleaner separation between the request path and the event path.

Practical Complexity & Trade-offs

The benefit of this design is that each part has one job. The gateway handles entry. The auth service checks identity and permission. The backup service handles jobs, snapshots, and metadata. Storage keeps chunks and indexes. Workers handle slow work in the background. That makes the API safer for large files. The downside is more moving parts. We must manage retries, idempotency, checksums, and versioning carefully. Chunk uploads are harder than one big upload, but they fail more safely. Immutable snapshots and optimistic locking protect correctness, but they add storage cost. We accept that cost because backup and restore must be trustworthy, resumable, and easy to recover over time.

Why Interviewers Ask This

Interviewers want to see clear API judgment. They check whether I can define resources, protect the service, and keep request and response flow correct. They also want to know if I understand idempotency, pagination, snapshots, retries, and restore safety. A strong answer shows that I can separate authentication from authorization, explain errors clearly, and keep the design scalable. It also shows that I can talk about trade-offs in simple words instead of only naming tools.

Interviewer may ask next
What if the same backup request is sent twice?

I would keep the same API and make the backup endpoints safely retryable. The main change is to require an Idempotency-Key on POST /v1/backups and also on chunk uploads when needed. That way, if the client retries after a timeout, the Backup Service can return the same job result instead of creating a second backup. I would also use checksums on each chunk, so the service can reject duplicate or corrupted data. This keeps the request path correct and protects storage from double writes. The downside is that the service must store idempotency history and dedupe state for a while, which adds storage and cleanup work. The rest of the design stays the same: the gateway still routes the request, auth still validates the caller, workers still handle slow work, and the event bus still carries progress updates.

What if files change while a backup or restore is running?

I would keep the same backup and restore APIs, but I would make snapshot checks stricter. The main change is to take the backup from a consistent snapshot and to use ETags or version checks when the client asks to restore files or folders. That means the Backup Service restores the exact saved version, not a moving target. If the current file changed after the snapshot, the restore still uses the snapshot data and does not guess. That keeps correctness and security strong, because the client only gets what was recorded. The downside is that the service may reject some updates or require a fresh snapshot, which can slow down a fast-changing system. The gateway, auth service, storage layer, workers, and event bus stay unchanged, and the client can retry with a newer snapshot later.

6. Design an ad frequency capping system.System DesignMediumNetflix

Question Details

Design a frequency-capping system for an advertising platform that prevents a user from seeing the same advertisement more than a configured number of times within a time window. Cover real-time cap checks, impression counting, multiple cap scopes, high QPS, low latency, multi-region consistency, delayed or duplicate events, retention, and failure behavior.

Short Interview Answer (30-60 seconds)

At a high level, this system decides whether a user has already seen the same ad too many times. The hard part is making that decision in real time without slowing ad delivery, while still counting impressions safely in the background. I would explain it in three flows: the fast cap check, the ad response path, and the background impression counting path. Redis makes the quick allow or deny decision, PostgreSQL stores the rules and long-term counts, and PHP-FPM workers keep the app stateless and scalable. The main trade-off is speed versus perfect freshness across regions.

Detailed Explanation

The goal is simple: show an ad only up to the allowed number of times in a time window. The hard part is that the decision must happen before the ad is shown, so it must be very fast. At the same time, the system must still count impressions safely and keep the rules clear. The diagram solves this by separating the live cap check from the background impression pipeline.

Useful Questions to Ask the Interviewer
  1. Do we cap by user plus ad, user plus campaign, device, IP, or all of them?
  2. If Redis is down, should we allow with safety limits or block the ad?
  3. Do all regions need the same result right away, or can there be a small delay?
Design an ad frequency capping system. diagram
How to Explain It in an Interview
1. Explain the goal and the main idea

At a high level, I would say this system protects ad frequency. It makes sure one user does not see the same ad too many times in a window like one hour or one day. The main challenge is that the check must happen before the ad is shown, so it has to be very fast. The diagram keeps that fast path separate from the slower counting work in the background.

2. Explain the request and cap check path

For the main request, the Web / Mobile App, Ad SDK / Player, or API Client sends an HTTPS request through the API Gateway / Edge. The edge layer adds WAF & DDoS protection, rate limiting, AuthN / AuthZ, and input validation. The Web Tier with Nginx or Apache can terminate TLS before traffic reaches the PHP app. Then the request reaches the Ad Delivery Service running on PHP 8.4 / 8.5 with PHP-FPM workers. That service builds the cap keys, does a multi-get to the Redis Cluster, and checks whether the user is still under the limit. If Redis says allowed, the service passes the request to the Ad Selection Service and returns the Ad Response. If the cap is reached, it returns no ad or a safe fallback.

3. Explain what is stored and why Redis is used

The Redis Cluster is the low-latency frequency store. It keeps counts and the window end time, with TTL matching the window length. The key idea is that each cap scope becomes its own key, such as user plus ad, user plus campaign, device plus ad, cookie plus ad, account plus ad, or a custom rule like geo or audience segment. Redis is not the main source of truth for the rules. It is the fast decision layer. The Configuration DB in PostgreSQL stores the cap rules, and the system can use cached configs if that database is unreachable. Common Services keep config, feature flags, logging, metrics, and tracing together. The app can also use PSR-16 / PSR-6 cache, an HTTP client, UUIDs, and DTOs as helper packages.

4. Explain how impressions are counted in the background

When the ad is shown, the Ad Delivery Service sends an impression event through the Impression Event Publisher. That event goes to the Message Queue, such as Kafka, SQS, or RabbitMQ. The Impression Processor, which runs as a PHP CLI worker, reads those events and updates the Persistent Store. It also writes aggregated counters to the relational database and can send older data to Analytics / OLAP and Cold Storage. This work does not block the user response, so the main path stays fast. The worker uses event_id to ignore the same event twice, and it can send failed items to the Dead Letter Queue.

5. Explain scale, failures, and trade-offs

The diagram keeps the PHP app stateless behind PHP-FPM workers, so it can scale horizontally. The Deployment layer runs in containers or VMs and can auto-scale. It also shows multi-region Redis, local reads and writes, and a small delay between regions. That keeps latency low, but some regions may be a little behind. The system also watches Metrics, Logs, Tracing, Alerts, and Dashboards for QPS, latency, cap hit rate, failures, DLQ, and high latency. The failure rules are practical. If Redis is down, the system can fail open with conservative limits or use a local in-memory LRU cache. If the queue is down, it can buffer locally and retry. If the config database is unavailable, it can use cached configs. The trade-off is simple: we get fast ad decisions, but we accept a little delay in background counts and cross-region sync.

Engineering Considerations / Design Trade-offs

The benefit is that the user gets a very fast ad decision. The downside is that the count is not updated in the same moment, because counting happens in the background. That is a good trade-off here, because the cap check must stay low latency. Redis gives quick reads, while PostgreSQL keeps the saved rules and longer-term records. The queue and workers make the system more reliable, but they add extra moving parts. Multi-region setup helps speed, but it can create a small delay between regions. The design accepts that small delay so the main path stays fast and stable.

Why Interviewers Ask This

Interviewers want to see if you can separate the fast path from the slow path. They also want to know if you can choose the right source of truth, use cache correctly, and handle duplicates, delays, and failures in a simple way. This question checks your judgment more than memorized terms. It shows whether you can explain trade-offs clearly.

Interviewer may ask next
What if Redis is down in one region?

I would keep the same basic design, but I would make the fallback stricter. The Ad Delivery Service would still try the Redis check first, because that is the fast path. If Redis is unavailable, the service can use a local in-memory LRU cache or fall back to cached config and conservative limits, so it does not show too many ads by mistake.

That keeps the system running, but it may allow fewer ads for a short time. It also means the result may not be as fresh as the Redis path. So the main downside is lower accuracy in that region during the outage.

What if we add a new cap scope like household or browser?

I would keep the same architecture and add the new scope as another key format. The Ad Delivery Service already builds cap keys before the Redis lookup, so this change fits there. The Configuration DB would store the new rule, and the Impression Processor would still count the same way in the background.

That keeps the design simple, because we do not need a new pipeline. We just add one more scope to the key builder and the cap rules. The downside is more rule management and more keys to track.

7. Design homepage viewport rendering with deduplication.System DesignMediumNetflix

Question Details

Design the backend and client interaction for rendering the initial viewport of a streaming-service homepage made of rows of titles. Prevent duplicate titles across visible rows, support incremental fetching and pagination, preserve low latency, and explain selection, ranking, caching, state, concurrency, and failure tradeoffs.

Short Interview Answer (30-60 seconds)

At a high level, this is a fast homepage viewport system for a streaming app. The main challenge is to load the first screen quickly and keep duplicate titles out of the visible rows. I would break the design into the request path, the ranking and dedup step, and the cache, database, and background update paths. The diagram uses edge checks, PHP-FPM workers, caches, databases, and an opaque cursor in the response. The main trade-off is speed versus freshness, so we rely on cached data and background refreshes.

Detailed Explanation

The goal is to render the first screen of the homepage with rows of titles. The hard part is keeping the page fast while making sure the same title does not show twice in the visible rows. The system also needs to remember where the user stopped, so the next request can continue from the right place. The diagram solves this with a fast request path, row ranking, global dedup checks, caches for speed, and background workers for refresh work.

Useful Questions to Ask the Interviewer
  1. How many rows and items should the first screen return?
  2. Should dedup apply only to the visible viewport, or also to later pages?
Design homepage viewport rendering with deduplication. diagram
How to Explain It in an Interview
1. Explain the goal and the main idea

At a high level, this is a read-heavy homepage request. The client asks for the viewport, and the service returns rows of titles with no duplicates in what the user can see. That is why the diagram starts with the client, then edge and auth guards, then the PHP application layer. The service must keep the response small and fast, because the homepage should feel instant.

2. Explain the request path

For the request path, the client sends user_id, device_id, session_id, locale, cursor, and row and item limits. The edge layer handles TLS, compression, geo routing, static assets, and basic protection. Then auth, authz, validation, and rate limits happen before the request reaches PHP 8.4 or PHP 8.5 in PHP-FPM workers. Inside the Homepage Controller, the app parses the request, resolves context, gets the row blueprint, fetches candidates per row, ranks them, and removes duplicates across the visible rows before it builds the JSON response.

3. Explain ranking, dedup, and pagination

The Row Orchestrator fans out to row services in parallel within one request. The Ranking & Dedup Engine normalizes scores, applies business rules, checks diversity and freshness, keeps a global seen set for the request, and truncates the final rows to the requested size. The cursor is opaque, which means it hides the internal offsets. The response also carries read_state_version, ab_bucket, and ttl_sec so the client can continue from the right state later.

4. Explain caches and data stores

The cache layer is the speed path. It has a viewport cache, a row blueprint cache, and a title metadata cache. On a cache hit, the app can answer faster. On a miss, it falls back to the User DB, Catalog DB, Interaction DB, and the Read State Store. The Read State Store tracks progress per row, so the next viewport stays consistent. This is cache-aside, so the main data still lives in the databases.

5. Explain background work, failures, and trade-offs

The background path uses the Event Queue and workers. Recompute workers refresh recommendations, popularity workers aggregate signals, and the Dedup Stats Worker keeps global dedup data fresh. This work does not block the homepage response. The system also uses Config Service, Feature Flags, A/B Testing, Telemetry Client, and external services for recommendations, content rules, and experiments. If a cache misses or an upstream service times out, the service can fall back to the blueprint or return the other rows. The main trade-off is simple: cached and background work make the page fast, but they can show slightly older results for a short time.

Engineering Considerations / Design Trade-offs

The benefit is a fast first screen and clean rows with no duplicate titles. The cache layer keeps common requests quick. The Row Orchestrator can work on several rows in parallel, so the page does not wait on one slow row. The downside is more moving parts. We keep a request-level seen set, cursor state, and background workers for refresh work. That adds complexity. We also accept that cached rows may be a little old for a short time, because speed matters more than perfect freshness on the homepage.

Why Interviewers Ask This

Interviewers want to see if you can split a real product problem into fast paths and background work. They also want to hear how you keep one title from showing twice, how you use caches without losing control of the main data, and how you talk about failures and trade-offs in simple words. It shows judgment, not memorization.

Interviewer may ask next
What if the product team says a title must never appear twice anywhere on the whole homepage, even across later pages?

I would keep the same basic design, but I would widen the dedup scope. Today the request-level seen set protects the visible rows in the first viewport. For this change, the same idea would also carry forward through the cursor, so later pages know which title IDs were already shown. The Row Orchestrator would still fetch candidates per row, but the Ranking & Dedup Engine would drop anything already used on earlier pages before it slices the final rows. The Read State Store would also need to remember the shown title set, not just the per-row progress. That keeps the result correct across pagination. The downside is that later pages may have fewer good choices, so some rows can look thinner. It also makes the cursor and state larger, which adds more work for the service.

What if clicks and watch events must change the homepage ranking within a few seconds?

I would keep the same request path, but I would make the background path more important. The Event Queue would collect watch and click signals, and the recompute workers would refresh the popularity and recommendation inputs more often. The Row Orchestrator would still serve the page from the fast cache and database path, but it would pick up the newer signals on the next refresh cycle. That keeps the homepage fast, because the user request still does not wait for analytics work. The change stays correct because the main response still comes from the same PHP Application Layer and the same Read State Store. The downside is more background load, and the homepage can still lag behind the newest clicks by a small amount.

8. Design an ad pacing system.System DesignHardNetflix

Question Details

Design an advertising pacing system for a large-scale streaming platform. Spread campaign spend or impressions over time, process real-time ad opportunities with low latency, track nested budgets, re-pace when traffic changes, prevent overspend across concurrent serving nodes, and cover the serving path, pacing control loop, event pipeline, storage, scaling, monitoring, and failures.

Short Interview Answer (30-60 seconds)

At a high level, I would treat this as a pacing control system for ad delivery. The tricky part is that the live ad request must stay very quick, but the system also has to track budgets and change pacing when traffic moves up or down. I would break it into three flows: the serving path, the pacing control loop, and the background event pipeline. The serving side checks pacing state in Redis before it returns an ad. The background path updates rollups and analytics. The trade-off is more moving parts, but much better control.

Detailed Explanation

The goal is to spread ad spend or impressions over time. The hard part is that the live ad request must stay very quick, but the system also has to track budgets and change pacing when traffic moves up or down. The diagram solves this by splitting the fast serving path, the pacing control loop, and the background event pipeline. I would explain it in that order, then show how Redis protects the live budget check and how the slower data pipeline keeps the pacing numbers fresh.

Useful Questions to Ask the Interviewer
  1. Should pacing be strict for spend, impressions, or both?
  2. How fast must the live ad path respond?
  3. What should happen if Redis or Kafka has trouble?
Design an ad pacing system. diagram
How to Explain It in an Interview
1. Explain the goal and the main idea

At a high level, this is a control problem. The live request path must be fast. The pacing path must stop overspend. The background path keeps the numbers fresh. The diagram uses the PHP Ad Serving Cluster for live traffic, the Pacing Service for budget control, and the event pipeline for later updates.

2. Walk through the real-time serving path

For the serving path, Streaming Clients send an Ad Request to Edge / CDN. Then the request reaches Nginx + PHP-FPM inside the PHP Ad Serving Cluster. The Ad Decision Service checks AuthN/AuthZ, validation, and sanitization first. It then looks up pacing state and reference data. If the campaign still has room, it builds the ad response and sends it back. The important point is that the PHP-FPM workers stay stateless, so each request is handled safely on its own.

3. Explain pacing state and atomic reservations

The Pacing Service is the safety gate. It uses a token bucket and budget hierarchy, so account, campaign, and line item limits can all be checked. Before the ad is served, it makes an atomic spend or impression reservation in the Redis Cluster. Atomic means the reservation happens in one safe step. That prevents two nodes from spending the same budget at once. The Reference Data Cache keeps campaign rules, targeting, and limits close to the hot path.

4. Explain background work and storage

After the request, the system sends impression and metric events in the background. The Event Ingest API accepts them, then Kafka or Redpanda carries them to Stream Processors. Those PHP long-running workers dedup, validate, and window the events. They write spend and rollup models, then ClickHouse stores analytics and PostgreSQL stores rollups. If an event fails, it goes to the DLQ, which is the dead letter queue. That keeps bad events from blocking the live path.

5. Explain scale, security, and trade-offs

The Pacing Optimizer runs as PHP CLI workers. It reads delayed rollups and adjusts delivery curves when traffic changes. Config change events can also feed the same control loop. Around that, the diagram shows Kubernetes multi-AZ deployment, observability, alerts, Vault, mTLS, WAF, and backups. The main trade-off is clear: the system gets stronger budget control and safer pacing, but it also becomes more complex and some updates arrive a little later than the live request.

Engineering Considerations / Design Trade-offs

The benefit is that the live ad path stays fast. Redis gives quick pacing checks, and the atomic reservation protects the budget. Kafka / Redpanda and long-running PHP workers move the slower work out of the request path. ClickHouse and PostgreSQL keep analytics and rollups separate from the hot path. The downside is more parts to run and watch. The control loop is not instant, so pacing changes can lag a little behind live traffic. We accept that because the main goal is safe delivery and low latency.

Why Interviewers Ask This

Interviewers want to see if you can split one hard problem into clear flows. They want to know if you can keep the hot path fast, choose a safe source of truth, and stop overspend across many nodes. They also look for good judgment on background work, monitoring, retries, and failure handling. A strong answer shows that you understand trade-offs and can explain them in simple words.

Interviewer may ask next
What if Redis is briefly unavailable and we still must protect budget?

I would keep the same basic design, but I would make the pacing check fail closed when the budget state cannot be confirmed. The serving path would still use the Redis Cluster for fast atomic reservations, but if the reservation is not safe, the service should not guess and should not overspend. In that case, the Ad Decision Service can return a safe fallback, or it can skip the ad for that request. The Event Ingest API and Stream Processors would still record traffic in the background, so the control loop can catch up later. The main trade-off is that we may reject or delay some ads during a short failure, but that is safer than spending past the limit.

What if traffic changes very quickly and pacing must react sooner?

I would keep the same architecture, but I would run the Pacing Optimizer more often and feed it fresher rollups from the Stream Processors. The hot serving path would still make fast local decisions, but the control loop would read the newest aggregated spend and impression data sooner, then adjust the token bucket rate and budget rollups in the Pacing Service. That keeps the same names and flows from the diagram. The important point is that the live request path still stays simple, while the control loop does the heavier thinking in the background. To keep the numbers stable, I would still use dedup and windowing in the stream processors before the optimizer reacts. The downside is that more frequent re-pacing adds more work, and the delivery curve can become more sensitive to short traffic spikes.

9. Design a publisher configuration rules system.System DesignHardNetflix

Question Details

Design a supply-side advertising configuration system for publisher-specific rules covering inventory eligibility, ad formats, floor prices, demand partners, privacy requirements, blocking rules, and revenue settings. Explain inventory modeling, rule inheritance and overrides, conflict resolution, real-time evaluation, versioning, rollout, auditing, storage, caching, validation, and monitoring.

Short Interview Answer (30-60 seconds)

At a high level, this is a system that lets publishers define ad rules and lets ad servers evaluate them very fast. The main challenge is that rule changes must be correct, versioned, and audited, but real-time requests still need a quick answer. I would explain it in three flows: rule creation and rollout, real-time evaluation with cache, and background audit and monitoring work. The design uses PHP 8.4/8.5 services, PostgreSQL, Redis, queues, and long-running workers. The trade-off is a little rollout delay for safer changes.

Detailed Explanation

The system lets publishers control how their inventory is used for ads. A publisher can set inventory eligibility, ad formats, floor prices, demand partners, privacy rules, blocking rules, and revenue settings. The hard part is that the ad server needs a fast answer, but every rule change must still be validated, versioned, audited, and rolled out safely. The diagram solves this by separating the write path, the real-time read path, and the background rollout and audit path.

Useful Questions to Ask the Interviewer
  1. Should one publisher rule override a global default, or should some fields merge?
  2. How quickly must a saved rule become active for ad serving?
  3. Do we need full rollback and long audit history for every version?
Design a publisher configuration rules system. diagram
How to Explain It in an Interview
1. Explain the goal and the main idea

At a high level, this is a rule system for publisher-specific ad settings. The goal is to return the effective config for each ad request. The difficult part is that many rules can apply at once, and the system must choose the right one every time. The diagram handles this with a PHP application layer, PostgreSQL stores, Redis cache, and background workers. It also shows rule inheritance, so a more specific rule can override a broader one.

2. Explain how rules are created and saved

For the create path, the request starts in the Publisher Admin Portal or the internal API clients. It goes through WAF and DDoS protection, rate limiting, authentication, authorization, and request validation. Then the Configuration API and Validation Service check the rule. The Inventory Service handles inventory eligibility, the Revenue & Pricing Service handles floor price and revenue settings, and the Conflict Resolution Engine applies deterministic rules. The system then saves the new version in the Rules DB, Inventory DB, and Version Store, and the Audit Service records the change.

3. Explain the real-time ad request path

For the read path, the Ad Server / Bidding request goes through the same security layer. Then it reaches the Rule Evaluation API. That API first checks the Redis Cache. On a cache hit, it returns the effective config fast. On a miss, it reads the main PostgreSQL stores, rebuilds the config, and writes the result back to cache. The Web Tier uses Nginx and PHP-FPM workers, so each request stays stateless and short.

4. Explain background work, rollout, and audit

The system does not do everything in the request path. Rule Change Event, Inventory Change Event, Rollout Event, and Audit Event go into the queues. Long-running PHP CLI workers then build indexes, warm the cache, process rollouts, export audits, and handle retries or the Dead Letter Queue. The Scheduler and Cron jobs run re-indexing, consistency jobs, and cleanup. Object Storage keeps exports, snapshots, backups, and artifacts.

5. Explain scale, safety, and trade-offs

The design is fast because real-time reads use cache, and heavy work moves to the background. The main database stays the source of truth, while Redis is only a performance layer. The downside is that a new rule may take a little time to reach every ad server during rollout or cache refresh. That is why the diagram adds strong validation, gradual rollout, auditability, monitoring, and alerting. It gives safer changes, but it also adds more moving parts.

Engineering Considerations / Design Trade-offs

The benefit is that ad servers get a fast answer from Redis and short PHP-FPM requests. The main PostgreSQL stores keep the real data safe. The downside is that cache and rollout updates can lag a little behind a write. That is why the system uses versioning, events, cache warmers, rollout workers, and a Dead Letter Queue. Another trade-off is more moving parts. That makes the system harder to run, but it gives better control, better audit history, and safer rule changes.

Why Interviewers Ask This

Interviewers want to see if you can split a complex rules problem into clear flows. They also want to know if you keep the main data in the right place, use cache correctly, and separate fast reads from background work. This question checks judgment on inheritance, conflict resolution, rollout, audit history, and monitoring. It shows whether you can explain trade-offs in simple words.

Interviewer may ask next
What if auditors need every rule version, rollout decision, and change history for a long time?

I would keep the same architecture, but I would lean more on the Version Store, Object Storage, and Audit Service. The Audit Service would export each change event, rollout event, and applied version into storage. The Versioning Service would keep snapshots and history so we can look back at older rules. That fits the diagram well because audit is already a separate background path. The real-time ad request path does not change, so latency stays low. The main thing to protect is correctness, so every version and rollout step must still link back to the saved rule data. The downside is more storage growth and more audit processing work in the background.

10. Design a scalable file backup system.System DesignHardNetflix

Question Details

Design a scalable file backup system using basic file-system primitives. Cover file discovery, metadata and content backup, incremental changes, deduplication, consistency during concurrent modification, restoration, crash recovery, storage layout, scheduling, retries, observability, and failure handling.

Short Interview Answer (30-60 seconds)

At a high level, this system safely backs up files and restores them later. The hard part is that files can change while a backup is running, so the backup must stay correct. I would explain it in three flows: discovery and backup creation, background chunking and storage, and restore plus recovery. The diagram uses PHP 8.4/8.5 services, PHP-FPM workers, long-running CLI workers, a queue with retries, PostgreSQL for metadata, Redis for hot state, and object storage for chunks and snapshots. The trade-off is more background work, but safer backups.

Detailed Explanation

The goal is to back up files safely and restore them later. The hard part is that files can change while a backup is running, and we still want one clean snapshot. We also want to avoid saving the same content twice. The diagram handles this by splitting the system into request handling, background workers, metadata storage, and blob storage.

Useful Questions to Ask the Interviewer
  1. Do we need full restore, folder restore, or single-file restore?
  2. How often should full and incremental backups run?
  3. Do we need encryption and tenant isolation for every backup set?
Design a scalable file backup system. diagram
How to Explain It in an Interview
1. Explain the goal and the main idea

At a high level, this is a safe storage system. The main job is to discover files, save metadata, save file chunks, and restore them later. The hard part is keeping the backup correct when files change during the run. So I would say the system keeps the request path small and pushes heavy work into background workers.

2. Explain the backup path

For the create path, requests can come from a backup agent, a web UI, or REST API clients. They first pass WAF, rate limiting, OIDC sign-in, RBAC access checks, and validation. Then the Backup API Controller and Job Orchestrator start the job. The File Discovery Service scans the file system, respects excludes, and records path, size, mtime, and mode. The Change Detector compares with the last snapshot. The Deduplication service uses chunking and hashes so the same data is stored once. The Manifest Service records versioned manifests for each backup. The common libraries keep path handling, hashing, encryption, compression, retries, and logging the same in every service.

3. Explain consistency and background work

To keep one stable view, the system uses OS-native snapshots, file-system freeze, or copy-on-write snapshots when needed. That way, the backup sees a consistent file set. The PHP-FPM web workers handle requests, but the CLI queue workers do the slower work in the background. The Message Queue sends jobs, retries, and failed jobs. The Retry Queue and DLQ help when a worker fails. The Notification Service can send alerts when a job finishes or fails.

4. Explain metadata, storage, and restore

The Metadata Service writes the official backup state into PostgreSQL. It stores users, policies, backup sets, manifest versions, file and chunk indexes, and job history. Redis keeps locks, hot manifests, and some rate-limit state. Object storage keeps encrypted, chunked data. It stores chunks, JSON manifests, snapshots, and a catalog index. The layout shown in the diagram is s3://backup/<tenant>/<backup-set>/<snapshot-id>/. For restore, the Restore API Controller reads the manifest first, finds the needed chunks, and rebuilds the file or folder at a point in time.

5. Explain scale, recovery, and trade-offs

The services are stateless, so we can scale PHP-FPM workers and CLI workers separately. The worker group uses autoscaling, a supervisor, health checks, memory limits, and graceful restart. Object storage can move data from hot storage to cool storage and then cold archive. Security is TLS in transit, encryption at rest, per-tenant isolation, and least-privilege access. Metrics, logs, tracing, and alerts help us spot failures fast. The trade-off is more moving parts, but we get safer backups, deduplication, retries, and faster normal requests.

Engineering Considerations / Design Trade-offs

The benefit is that the user-facing path stays short. PHP-FPM handles the request quickly, and the queue workers do the heavy backup work later. Deduplication saves storage because the same chunk is stored once. Redis makes locks and hot manifests faster, but it is only a speed layer. PostgreSQL keeps the official backup state, and object storage keeps chunks cheaply. The downside is more components to run and watch. We accept that because backups must be safe, resumable, and easy to restore.

Why Interviewers Ask This

Interviewers want to see whether you can break a storage problem into clear flows. They want to know if you can keep the main request fast, protect the official backup state, and handle files that change during backup. They also look for good judgment around deduplication, retries, recovery, observability, and simple trade-offs. A strong answer shows that you can build a safe design, not just name services.

Interviewer may ask next
What if a file changes while the backup is running?

I would keep the same design, but I would make every backup job resumable. If a file changes while the job is running, the worker should read from the stable snapshot, not from live files. That is why the diagram shows consistency during writes with OS-native snapshots, file-system freeze, or copy-on-write snapshots. The metadata in PostgreSQL can store the backup set, manifest version, chunk index, and job status, so a worker can continue from the last safe step after a crash. Redis locks help stop two workers from writing the same job at once, and the Retry Queue can send the job back to another worker. The downside is more state to track and more recovery logic, but the backup stays correct and a partial run does not waste all the earlier work.

What if Redis or the queue is down?

I would keep the same architecture, but I would treat Redis and the queue as replaceable helpers, not the source of truth. PostgreSQL still owns the official backup state, and object storage still keeps the chunks and manifests. If Redis is slow or empty, the service can read the manifest from PostgreSQL and continue. If the queue is down for a short time, the request path should still accept the backup request and record the job status, then the scheduler can retry later. The DLQ helps us isolate jobs that keep failing. The downside is that some restores or retries may take longer during an outage, but the system keeps moving and does not lose the saved backup data at all.

Disclaimer: This interview guide is for educational and informational purposes only. It is designed to help readers prepare, but it does not guarantee any interview result, hiring decision, offer, or outcome. Interview questions, hiring criteria, and preferred answers can vary by employer, interviewer, industry, location, and time. The examples and explanations reflect the authors' research and judgment, are provided without warranties of any kind, and should not be treated as the only correct approach. Diagrams are simplified illustrations intended to highlight the main components and their interactions; actual systems and implementations may be more complex. Alternative approaches may be equally valid or better suited to a particular question, context, or interviewer. To the fullest extent permitted by applicable law, the author, contributors, and publisher are not liable for decisions made, actions taken, or losses incurred based on this guide.

Company Notice: This guide is an independent educational resource and is not affiliated with, endorsed by, sponsored by, or approved by the company named in this guide. Company names are used only to identify interview experiences commonly reported by candidates. Interview practices can change without notice, and inclusion of company-specific content does not mean these questions are official, complete, or guaranteed to be asked. To the fullest extent permitted by law, the author, contributors, and publisher are not responsible for outcomes related to use of this material.