460 Python Developer Interview Questions & Answers

154 top • 31 Amazon • 49 Google • 44 Netflix • 48 Meta • 41 NVIDIA • 47 Apple • 46 Microsoft

Python Developer icon

Questions with Detailed ExplanationsWith Detailed Explanations

(Last Updated: August 28, 2026)

111. Design an online collaborator platform?System DesignHard

Question Details

Design an online collaboration platform where many users can create or join a shared document and edit it at the same time. The system should show live changes, user presence, cursors, comments, version history, and reconnect users after a network failure. Explain how edits are ordered and merged, how duplicate operations are prevented, how document state is stored, how WebSocket connections are scaled, how offline edits are handled, and how the system recovers when a collaboration server fails.

Short Interview Answer (30-60 seconds)

At a high level, this system lets many users edit the same document in real time. The hard part is keeping every user in the same order while handling reconnects and server failures. I would explain it in four parts: route each document to one Session Owner, commit edits to the Operation Log, broadcast live updates, and recover clients from snapshots plus missed operations. The main trade-off is strong ordering versus more coordination.

Detailed Explanation

The goal is to let many users edit one shared document and see changes quickly. The difficult part is keeping every client in the same order when edits happen at the same time. The system must also handle comments, presence, offline work, reconnects, and server failures. The diagram solves this with one Session Owner per document, Operational Transformation, a durable Operation Log, snapshots, and short-lived connection and presence stores.

Useful Questions to Ask the Interviewer
  1. Which user flows and system capabilities are required for the first version?
  2. What traffic, data volume, latency, and availability targets should I design for?
  3. Which consistency, security, geographic, and cost constraints matter most?
Design an online collaborator platform? diagram
How to Explain It in an Interview
1. Create or join the document

A user creates a document or joins an existing one through the WebSocket Gateway. The gateway checks authentication, permissions, request limits, and tenant rules.

The Document Router hashes the document_id. It sends every connection for that document to the same Collaboration Session Owner.

The client receives the current snapshot and any operations after the snapshot sequence. This gives the client the latest document state before live editing starts.

The Connection Registry stores which WebSocket node owns each user and device connection. This is short-lived routing data and is updated when clients reconnect.

2. Keep one safe owner for each document

Each Session Owner holds a lease for one document. The lease contains document_id, owner_epoch, and lease_expiry.

The owner renews the lease with heartbeats. If renewal fails, it must stop accepting new edits.

When another node takes over, it receives a higher owner_epoch. Only the newest epoch may append operations. This stops an old server from writing after a network delay.

3. Order and commit edits

The client sends an edit with operation_id and base_sequence. The Session Owner checks permissions and ignores duplicate operation IDs.

The service uses Operational Transformation, or OT. OT changes a new edit so it still works after other users' earlier edits.

The owner assigns the next document sequence. It appends the operation to the Operation Log with document_id, sequence, owner_epoch, and operation_id.

The Operation Log is the source of truth. It rejects writes from an older owner_epoch. The sender is acknowledged only after the log commits the operation.

The Session Owner broadcasts the committed operation directly after the log commit. It does not wait for the Operational Store update.

The current document state may update immediately after. If that update fails, it can be retried or rebuilt from the log.

4. Handle pressure and slow clients

Each document session uses a bounded input queue. The service limits operations per user and document, pending bytes per connection, and queue length.

If a limit is reached, the service returns a retry response such as 429. Clients that cannot receive updates fast enough may be slowed or disconnected.

These limits stop one busy document or slow client from hurting the whole system.

5. Handle presence, comments, and side work

Presence and cursor updates go to the Presence Store. This data is temporary and expires when heartbeats stop. It is not written to the permanent Operation Log.

Comments are saved in the Operational Store. They use their own IDs and timestamps. They do not use the document edit sequence.

After a comment is saved, it is broadcast to connected clients. Mentions can create notifications in the background.

Search indexing, notifications, audit logs, and analytics also run in the background. Their failure does not block the edit acknowledgement or live broadcast.

6. Reconnect and recover safely

A reconnecting client sends document_id, last_applied_sequence, and pending operation IDs. The server sends all missed operations after that sequence.

The client applies those operations first. Its offline edits are then transformed against the newer server edits and sent again.

The Snapshot Store creates snapshots from committed operations. Every snapshot stores snapshot_sequence, which is the last operation included. Recovery loads the snapshot and then applies later operations.

If a Session Owner fails, a new owner reads the last committed sequence from the Operation Log and takes over with a higher epoch. Uncommitted client edits may need to be resent. WebSocket nodes keep temporary connection state, but permanent document data stays in the log and stores.

Engineering Considerations / Design Trade-offs

The benefit is that every document has one clear edit order. The Operation Log keeps edits safe before users see them. The downside is that one Session Owner must handle all edits for one document, so very active documents can become hot. OT keeps edits consistent, but it adds transform work. Bounded queues and connection limits protect the system, but some clients may receive a retry response. Snapshots make loading faster, while background indexing and analytics may appear later.

Why Interviewers Ask This

The interviewer wants to see whether the candidate can handle real-time ordering, duplicate edits, reconnects, offline work, and safe failover. They also want to test WebSocket scaling, durable logs, snapshots, comments, presence, and conflict handling. A strong answer explains both the normal edit path and how the system recovers after a client or server failure.

Interviewer may ask next
What happens if the current Session Owner fails while users are editing?

A new Session Owner must take over safely. The Document Router selects another healthy node for that document.

The new owner receives a higher owner_epoch and a new lease. It reads the last committed sequence from the Operation Log. The log rejects any later write from the old owner because its epoch is now stale.

Connected users reconnect through the WebSocket Gateway. The Connection Registry is updated with their new WebSocket node. They send their last_applied_sequence and pending operation IDs.

The server returns missed committed operations first. Clients then rebase and resend any uncommitted edits.

The benefit is that committed edits are not lost. The downside is a short pause while clients reconnect, and some uncommitted edits may need to be sent again.

How would you handle edits made while a user is offline?

The client stores offline edits locally with unique operation IDs and the last known base_sequence.

When the connection returns, the client first asks for all committed operations after its last_applied_sequence. It applies those operations to reach the latest server state.

The offline edits are then transformed against the missed edits using OT. After that, the client sends them to the current Session Owner.

The owner checks duplicate operation IDs, assigns new document sequences, and commits them to the Operation Log. If an operation was already accepted before the disconnect, the duplicate check prevents it from being applied twice.

The benefit is that users can keep working offline. The downside is that large offline changes may need more transform work and may create visible conflicts.

112. Design a scalable URL-shortening service?System DesignHard

Question Details

Design a scalable URL-shortening service similar to Bitly or TinyURL. The system must generate unique short links, redirect users to the original URLs with low latency, support optional custom aliases and expiration dates, prevent alias collisions, and collect click analytics asynchronously. Explain how you would generate globally unique keys, partition and replicate the URL mappings, cache popular redirects, prevent database-to-cache inconsistency, apply rate limits, and preserve availability when cache or database nodes fail.

Short Interview Answer (30-60 seconds)

At a high level, this is a read-heavy system. Creating a short link must be correct, but redirects must be very fast because they happen much more often. I would explain it in three parts: create the short link, redirect the user, and record clicks in the background. The Metadata Database keeps the official mapping. The Redirect Cache makes reads fast. The trade-off is that cache or replica data may be a little old.

Detailed Explanation

The goal is to turn a long URL into a short code and return the original URL very quickly when someone opens that code. The hard part is keeping link creation correct while making redirects fast and available. The diagram solves this with a separate create path, redirect path, and analytics path.

Useful Questions to Ask the Interviewer
  1. Which user flows and system capabilities are required for the first version?
  2. What traffic, data volume, latency, and availability targets should I design for?
  3. Which consistency, security, geographic, and cost constraints matter most?
Design a scalable URL-shortening service? diagram
How to Explain It in an Interview
1. Explain the main idea

This is mainly a read-heavy system. A link is created once, but users may open it many times.

The Metadata Database keeps the official mapping between the short code and long URL. The Redirect Cache is only used to make reads faster. Click analytics runs in the background, so it does not slow down the redirect.

2. Create the short link

The client sends a long URL. The request may also include a custom alias and an expiration time.

The API Gateway and Rate Limiter checks the request, applies rate limits, and blocks bad input. Then the URL Service decides how to create the short code.

If the user gives a custom alias, the service changes it to lowercase and reserves it with a UNIQUE rule in the Metadata Database. This prevents two users from using the same alias.

If there is no alias, the service creates a Snowflake-style number. This number uses time, a unique worker ID, and a sequence. The service then changes the number into Base62 text. Base62 only makes the code shorter. It does not make it unique.

The URL Service writes the mapping to the Metadata Database first. Only after the database write succeeds does it populate or invalidate the Redirect Cache. This keeps the cache from holding data that was never saved.

3. Redirect the user

When a user opens a short link, the request first reaches the Edge or CDN. It handles DNS, TLS, and DDoS protection. Then it sends the request to the Redirect Service.

The Redirect Service checks the Redirect Cache first. If the code is found and not expired, the service gets the long URL and expiration time. It then returns a 302 or 307 redirect.

If the cache misses or the entry has expired, the service reads from a Metadata DB replica. A replica is a read copy of the main database. It may be a little behind.

The service checks the expiration time again. If the link is valid, it returns the long URL and adds the result to the cache. The cache time must not go past the link's expiration time. If the link is missing or expired, the service returns 410 Gone or a custom page.

4. Record click analytics

After a valid redirect lookup, the Redirect Service sends a ClickRecorded event to the Event Queue. Workers process the event and store the result in the Analytics Store.

The create path may also send a separate ShortLinkCreated event. These are two different events. Because analytics runs in the background, slow reports do not delay the redirect.

5. Scale and handle failures

The Metadata Database is split by hash(short_code). The leader handles writes, while replicas handle reads. Replicas may have a small delay.

If the cache fails, the Redirect Service reads from replicas. Rate limits, circuit breakers, short timeouts, and request coalescing protect the database. Request coalescing means many requests for the same code share one database lookup.

If the database leader fails, writes may stop briefly while a new leader takes over. Redirects can still continue from the cache during that time. The system also validates URLs, blocks abuse, uses HTTPS, and applies separate rate limits to create and redirect requests.

Engineering Considerations / Design Trade-offs

The benefit is fast redirects because popular links come from the cache. The downside is that cache or replica data may be a little old. Writing to the database first keeps the mapping correct. The cache is updated only after that. A short cache time finds changes sooner, but it causes more database reads. Replicas improve availability, but they may be behind the leader. Analytics runs in the background, so click reports may appear later.

Why Interviewers Ask This

The interviewer wants to see whether the candidate can separate a write path from a much busier read path. They also want to check unique code generation, custom aliases, caching, expiration, database scaling, failure handling, rate limits, and background analytics. A strong answer keeps the data correct while making redirects fast and available.

Interviewer may ask next
How would you make a new short link work immediately if the read replicas are behind?

I would keep the same design, but I would change the first read after creation.

After the Metadata Database leader saves the new mapping, the URL Service can place it in the Redirect Cache before returning success. Then the new short link can work right away from the cache.

If the cache update fails, the first read can go to the leader instead of a replica. This is useful because replicas may be a little behind.

The leader still keeps the official data. The cache only helps with speed.

The benefit is that the user can open the new link immediately. The downside is more routing logic and a little more load on the leader.

What would you do if the Redirect Cache failed during heavy traffic?

The Redirect Service would read from the Metadata DB replicas instead.

But it should not send every request to the database without limits. That could overload the replicas.

I would use rate limits, short timeouts, and circuit breakers. A circuit breaker stops sending requests when the database is already failing.

I would also use request coalescing. If many users ask for the same short code, the service sends one database request. The other requests wait for the same result.

If the replicas are still too busy, the service may return a controlled 503 error for some requests. The benefit is that the database stays healthy. The downside is that some redirects may fail for a short time.

113. Design a distributed job scheduler?System DesignHard

Question Details

Design a distributed job scheduler in Python that lets users submit one-time and recurring jobs, cancel jobs, view status, and run jobs at their scheduled time. The system must support priorities, bounded retries with exponential backoff, worker heartbeats, execution leases, and safe recovery when a scheduler or worker fails. Explain how you would store schedules durably, prevent two workers from owning the same job, handle long-running and stuck jobs, apply backpressure and tenant quotas, and use Python processes, containers, or asyncio workers for different workload types.

Short Interview Answer (30-60 seconds)

At a high level, this system stores jobs safely and runs them at the right time. The hard part is preventing duplicate ownership while still recovering from crashes. I would explain it in four parts: submit and store the job, schedule due jobs, run them with leases, and report results. The Job Store keeps the official data. The trade-off is at-least-once execution, so a job may run more than once after a failure.

Detailed Explanation

The goal is to let users create one-time or recurring jobs and run them at the correct time. Users must also cancel jobs and check their status. The difficult part is handling crashes without losing jobs or letting two workers own the same job. The design solves this with durable storage, atomic scheduler claims, execution leases, heartbeats, retries, and separate worker types.

Useful Questions to Ask the Interviewer
  1. Which user flows and system capabilities are required for the first version?
  2. What traffic, data volume, latency, and availability targets should I design for?
  3. Which consistency, security, geographic, and cost constraints matter most?
Design a distributed job scheduler? diagram
How to Explain It in an Interview
1. Submit and store the job

The user sends a create, cancel, or status request through the API Gateway. This layer checks the user, validates the request, applies rate limits, and checks the tenant quota.

For a new job, the Job Service saves the job and schedule in the Job Store. The first state is SCHEDULED. The Job Store is the source of truth, which means it keeps the official job data.

A one-time job has one planned run. A recurring job also stores its schedule and next_run_at. A JobCreated event may be sent for notifications or reporting, but it does not send the job to the Ready Queue.

2. Find jobs that are ready to run

The Scheduler Cluster reads jobs whose next_run_at is now or earlier. Several scheduler instances may read at the same time, so each job must be claimed with one atomic update.

The winning scheduler changes the state from SCHEDULED to QUEUED. It also saves claimed_at and claim_expiry. Only the winner sends the job to the Ready Queue.

If a scheduler crashes before queueing the job, another scheduler finds the expired claim. It can reset the job and try again. This lets the system recover claimed jobs after the scheduler comes back.

3. Run the job safely

A worker pulls a job only when it has free capacity. Before running it, the worker checks the latest job state. If the job is CANCELLED or already finished, the worker skips it.

If the job is valid, the worker gets an execution lease. A lease gives one worker temporary ownership. It includes a lease_version and lease_expiry.

The worker sends heartbeats while the job is running. A heartbeat extends the lease. Long-running jobs must keep sending them. If the worker stops sending heartbeats, the lease expires and another worker may try the job.

For a running job, the worker receives a cancellation request when the job type supports it. Stopping is best-effort, so the system cannot always stop the job immediately.

The worker type depends on the work. asyncio workers are good for network and database waiting. Python processes are better for CPU-heavy code. Containers are useful for isolated or dependency-heavy jobs. Simple blocking jobs can use normal synchronous workers.

4. Save results, retry failures, and update status

When the worker finishes, it reports the result with the lease_version. The Job Service checks that this version is still current. It accepts the current worker and rejects an old worker.

A successful job becomes SUCCEEDED. A cancelled job becomes CANCELLED. A failed job uses bounded retries. The Retry Manager calculates a later next_run_at with exponential backoff. If the job has used all allowed attempts, it becomes FAILED. Otherwise, it returns to SCHEDULED.

For a recurring job, success creates the next planned run. This is different from a retry. A retry repeats the same failed run.

JobStateChanged events go through the Event Bus. The Status View Updater uses them to update the Status Read DB. The Job Query Service reads that view when users ask for status.

5. Handle scale and failure

The Ready Queue is split by priority and tenant. Queue limits and worker concurrency provide backpressure, which means the system accepts only the work it can handle.

Tenant quotas stop one customer from using all workers. The Job Store uses a leader or consensus group for writes and replicas for availability. The main trade-off is at-least-once execution. A job may run twice after a crash, so job handlers should be safe for retries.

Engineering Considerations / Design Trade-offs

The benefit is that jobs are not lost when a scheduler or worker fails. Leases and heartbeats let another worker take over stuck work. The downside is that a job may run more than once after a failure. Job code should therefore be safe when repeated. Short leases find failures faster, but they need more heartbeats. Long leases use fewer heartbeats, but recovery is slower. Priority queues help urgent jobs, but fair ordering across many tenants is harder.

Why Interviewers Ask This

The interviewer wants to see whether the candidate can store schedules safely, stop two workers from owning one job, and recover from crashes. They also want to check retries, cancellation, recurring jobs, backpressure, tenant fairness, and Python worker choices. A strong answer explains both the normal flow and what happens when part of the system fails.

Interviewer may ask next
How would you handle a worker that finishes after its lease has already expired?

I would reject the old worker’s result. Every execution lease has a lease_version. The worker sends that version when it reports success or failure.

The Job Service reads the current lease from the Job Store. If the versions match, the result is accepted. If they do not match, the worker is stale and its update is rejected.

This protects the job state after another worker takes ownership. However, the old worker may already have made an outside change, such as sending an email. That is why the job handler should use a stable request key or check whether the action was already completed.

The benefit is safe job state. The downside is that outside actions may still happen twice unless the job code also protects them.

How would you stop one tenant from filling the whole queue?

I would apply limits before the job enters the system and again during scheduling. The API Gateway and Job Service check how many jobs the tenant may create. The Scheduler also checks how many jobs that tenant already has running or waiting.

The Ready Queue uses tenant partitions, priorities, and tenant quotas. This prevents one tenant from taking all queue and worker capacity. Workers also use bounded concurrency, so they accept only a safe number of jobs.

When the queue reaches its limit, the API can reject or slow new submissions according to the configured backpressure rule. This keeps the system stable during a traffic spike.

The benefit is fair use and better stability. The downside is more scheduling logic, and a tenant may wait even when another tenant is not using its full share.

114. What is a REST API?NEWAPI DesignEasy

Question Details

Define a REST API in practical HTTP terms. Explain resources and URLs, HTTP methods, representations such as JSON, status codes, stateless requests, validation, consistent errors, authentication, pagination, idempotency, and caching. Use one small Python service example and distinguish REST from a Python framework or a transport protocol.

Short Interview Answer (30-60 seconds)

At a high level, a REST API lets applications work with resources through standard HTTP rules. In this design, a client calls a Python REST API service using URLs like /users and /users/{id}. GET reads users, POST creates one, PUT updates one, and DELETE removes one. JSON carries resource data, while HTTP status codes explain the result. Each request is stateless and can carry a Bearer token for authentication. Pagination and caching improve efficiency. The trade-off is more API design work in exchange for a predictable interface.

Detailed Explanation

This question asks how two programs can communicate in a clear and predictable way. The client needs simple ways to list users, get one user, create one, update one, or delete one. The service must also clearly say whether each request worked or failed. It should protect requests, reject bad input, and handle large result lists efficiently. The main challenge is keeping these rules consistent for every client. I would explain the same user API shown in the diagram and connect each REST idea to that practical example.

Useful Questions to Ask the Interviewer
  • Are we discussing a simple public HTTP API or an internal service API?
  • Should I focus only on REST basics, or also explain security and performance?
  • Is the user resource shown in the diagram enough for the example?
What is a REST API? diagram
How to Explain It in an Interview
1. Start with resources and URLs

I would start by saying that REST is an architectural style for web APIs. A resource is a thing the API manages, such as a user. Each resource has a URL that identifies where clients work with it. The diagram uses /users for the user collection. It uses /users/{id} for one specific user. Good REST URLs normally use resource names rather than action verbs. REST is not a Python framework. It is also not a transport protocol like HTTP. A Python framework can implement REST rules, while HTTP carries the requests and responses.

2. Use HTTP methods for actions

The request uses an HTTP method to say what action is wanted. GET /users lists users. GET /users/{id} gets one user. POST /users creates a new user. PUT /users/{id} updates one user. DELETE /users/{id} removes one user. This keeps the URLs focused on resources. The client sends these HTTP requests through the network to the Python REST API service. The service processes the request and sends an HTTP response back to the client.

3. Send clear request and response data

JSON is the main representation shown in the diagram. A representation is the data format used to describe a resource. For example, POST /users sends Content-Type: application/json with {"name":"Asha","email":"a@x.com"}. A successful create returns 201 Created with the new user data. A successful read returns 200 OK. The update example also returns 200 OK. A successful delete returns 204 No Content. These status codes tell the client what happened without making it guess.

4. Keep requests stateless and validate input

Each request should contain everything needed to handle that request. This is called statelessness. The server does not depend on hidden client state from an earlier request. The service should also validate incoming data before processing it. Invalid client input uses 400 Bad Request. A missing resource uses 404 Not Found. An unexpected server problem uses 500 Internal Server Error. The diagram also shows a consistent JSON error shape with error, message, and status fields. A consistent format makes failures easier for clients to handle.

5. Authenticate protected requests

The diagram shows requests carrying Authorization: Bearer <token>. A Bearer token is a credential the client sends in an HTTP header. The API uses authentication to check whether the caller has valid credentials. The diagram uses 401 Unauthorized when authentication is required. HTTPS is also shown as part of securing the API because it protects data while it travels across the network. Authentication is separate from the REST resource model. It protects access while the same resource URLs and HTTP methods remain unchanged.

6. Handle large lists, repeated calls, and caching

For a large user collection, the diagram uses pagination. The client can call GET /users?page=1&limit=10. The response can include a next link such as /users?page=2. This avoids returning every user in one response. The diagram also treats GET, PUT, and DELETE as idempotent. Idempotent means repeating the same operation should not create extra changes. POST is not shown as idempotent. For repeated reads, caching headers can reduce server work. The diagram specifically shows Cache-Control, ETag, and Last-Modified as caching mechanisms.

7. Close with the practical REST idea

The main idea is consistency. Clients know which URLs represent resources, which HTTP methods perform actions, and which status codes describe results. They also receive predictable JSON data and errors. The Python REST API service is one implementation of these rules. REST itself is not the Python framework and is not HTTP itself. The benefit is an API that is easier for different clients to understand. The downside is that the team must carefully define URLs, methods, validation, authentication, errors, pagination, idempotency, and caching behavior.

Practical Complexity & Trade-offs

The benefit of this design is consistency. The same resource URLs and HTTP methods are easy for clients to learn. Status codes and one error format make failures easier to handle. Stateless requests keep each call independent. Pagination reduces how much data a large list returns at once. Caching can reduce repeated server work and improve response speed. Authentication and HTTPS protect access and network traffic. The downside is extra design work. The team must define validation, page behavior, cache rules, and error responses carefully. Idempotency also matters when clients repeat requests after network problems. GET, PUT, and DELETE can follow idempotent behavior, while POST can create another resource when repeated. We accept this work because clear rules make the API easier to use and maintain.

Why Interviewers Ask This

Interviewers ask this to check whether you understand REST as practical API design, not just as a definition. They want to see clear resource URLs, correct HTTP methods, status codes, and request-response behavior. They also look for statelessness, validation, consistent errors, authentication, pagination, idempotency, and caching. A strong answer separates REST from a Python framework and from HTTP itself. The key skill is explaining why each choice helps clients and servers communicate predictably.

Interviewer may ask next
How would this REST API handle a very large number of users?

I would keep the same /users resource and change how GET /users returns the collection. The diagram already shows pagination with page and limit query parameters. For example, the client can call GET /users?page=1&limit=10. The response returns only that page and can include a next link such as /users?page=2. This keeps each response smaller and avoids sending every user at once. For repeated reads, I would also use the caching mechanisms shown in the diagram. Cache-Control, ETag, and Last-Modified can help avoid unnecessary data transfers when content has not changed. The resource URLs, HTTP methods, Bearer-token authentication, validation, and status-code rules stay the same. The main downside is more client logic. Clients must follow page links and correctly handle cache behavior. We accept that complexity because pagination and caching make large read operations more efficient.

What happens if clients repeat requests or send invalid authentication?

I would keep the behavior predictable by following the idempotency and authentication rules shown in the diagram. GET, PUT, and DELETE are treated as idempotent operations. This means repeating the same operation should not create extra changes. For example, repeating PUT /users/{id} should leave the user in the same requested state. Repeating DELETE /users/{id} should not delete another resource. POST is different because repeating POST /users can create another user. For protected calls, the client sends Authorization: Bearer <token>. The Python REST API service uses authentication to check the credential. The diagram uses 401 Unauthorized when authentication is required. Invalid client data uses 400 Bad Request, while a missing user uses 404 Not Found. The downside is that clients must understand these different outcomes. The benefit is clear and consistent behavior when requests fail or are repeated.

115. How would you design a FastAPI endpoint to handle timeouts and partial failures?API DesignHard

Question Details

Design a FastAPI endpoint that calls several downstream services. Explain connect and read timeouts, cancellation, retries, circuit breakers, partial responses, error mapping, request tracing, idempotency, and how to avoid leaving inconsistent state.

Short Interview Answer (30-60 seconds)

At a high level, I would design the FastAPI endpoint as a resilient aggregator. The client calls POST /aggregate with an Idempotency-Key. The service validates the request, checks idempotency, then fans out calls to downstream services using connect and read timeouts. The orchestrator uses retries with backoff, cancellation, and caller side circuit breakers. It maps each success or failure into a partial response. The trade-off is that users may receive incomplete data, but the endpoint stays fast and predictable.

Detailed Explanation

The goal is to build a FastAPI endpoint that calls several downstream services without letting one slow service break the whole request. The main challenge is to handle timeouts, retries, and partial failures while keeping state consistent. The diagram solves this with an aggregator, idempotency, caller side resilience, tracing, and a partial response builder.

Useful Questions to Ask the Interviewer
  1. Which clients and core use cases must the API support?
  2. What authentication, authorization, and data-validation rules should I assume?
  3. What scale, error handling, idempotency, and versioning requirements matter?
How would you design a FastAPI endpoint to handle timeouts and partial failures? diagram
How to Explain It in an Interview
1. Start with the API boundary

I would start by saying this endpoint is an aggregation API. The client sends an HTTPS request to POST /aggregate. It also sends an Idempotency-Key, which lets retries reuse the same logical request.

The request enters the FastAPI Service and goes through Request Validation. Validation checks that the request shape is acceptable before any downstream call is made. This avoids wasting work on invalid input.

2. Check idempotency before doing work

The Idempotency Check talks to the Idempotency Store. The store checks whether the same key already has a completed result or a processing lock. This protects the endpoint when a client retries after a timeout.

If a completed result already exists, the service can return it safely. If the request is new, the service continues into the Orchestrator / Aggregator. After the final response is built, the completed response can be stored for safe retry.

3. Call downstream services with clear limits

The Orchestrator / Aggregator makes fan-out parallel calls. Fan-out means calling several services during one user request. In the diagram, it calls User Service, Profile Service, and Recommendation Service over HTTPS plus mTLS.

mTLS means both sides prove their identity during the encrypted connection. Each call has a connect timeout and a read timeout. The connect timeout protects connection setup. The read timeout protects the wait for the response body.

4. Handle failures inside the orchestrator

The orchestrator owns retries with backoff. Backoff means waiting a little longer between retry attempts. This helps with short failures without flooding a bad dependency.

It also owns cancellation. If the client disconnects or the overall request deadline is reached, in-flight downstream calls should be cancelled. The caller side circuit breaker is also inside the orchestrator. It fails fast when a downstream service is unhealthy.

5. Build the partial response

Downstream services return success, error, or timeout. The orchestrator sends collected successes and failures to the Error Mapping & Partial Response Builder. That builder maps exceptions to HTTP friendly error details.

The response can contain available data and per service status. For example, user data may succeed while profile times out. The client still receives an HTTPS partial response instead of waiting forever.

6. Keep state consistent and observable

The Primary Database should store only confirmed successful state. Side effects should be published to the Message Broker only after a successful commit. This avoids recording failed partial data as success.

Tracing / Observability receives trace spans, logs, and metrics. This gives end to end visibility through request_id and spans. Configuration Service provides timeouts, retries, and circuit breaker policy. Secret Manager provides mTLS certificates, tokens, and API keys.

The main trade-off is user experience versus completeness. Partial responses keep the endpoint responsive, but the client must understand which services failed.

Practical Complexity & Trade-offs

The benefit is that one slow downstream service does not block the whole endpoint. Connect and read timeouts protect latency. Retries with backoff handle short failures, but too many retries can increase load. Caller side circuit breakers reduce cascading failures, but they may return degraded data while a service recovers. Idempotency makes client retries safer, but it needs a store and careful response handling. Persisting only confirmed successful state avoids inconsistent data. Publishing side effects after commit is safer, but it adds operational complexity.

Why Interviewers Ask This

Interviewers ask this to test API reliability judgment. They want to know if the candidate can separate request validation, downstream calls, response mapping, and side effects. They also check whether the candidate understands timeouts, retries, cancellation, circuit breakers, tracing, idempotency, and consistent state. A strong answer explains trade-offs instead of only naming tools.

Interviewer may ask next
What changes if the Profile Service is slow for several minutes?

I would keep the same endpoint and make the caller side circuit breaker protect the Profile Service call. The affected flow is Orchestrator / Aggregator to Profile Service. After enough failures or timeouts, the circuit breaker opens and the orchestrator stops calling that service for a short period.

During that time, the Error Mapping & Partial Response Builder returns a partial response. It can include user data and recommendations if they succeed, while marking profile as unavailable or timed out. Tracing / Observability records the failures so the team can investigate.

Correctness is maintained because failed profile data is not stored as successful state. The downside is that users may see missing profile data until the breaker half opens and the service recovers.

How would you avoid duplicate side effects when the client retries the request?

I would use the Idempotency-Key as the stable identity for the client operation. The affected flow is Client / Web App to Idempotency Check and Idempotency Store. Before doing downstream work, the service checks whether the key already has a result or a processing lock.

If the same request is already complete, the stored response is returned. If it is still running, the API can return the current processing state or prevent duplicate execution. After building the response, the completed result is stored for safe retry.

For state changes, the service persists only confirmed successful state. It publishes side effects after successful commit. The downside is that the idempotency store must be reliable and must expire old keys carefully.

116. How would you design a fault-tolerant API?API DesignHard

Question Details

Design an API that remains useful when dependencies are slow or unavailable. Explain timeouts, bounded retries, exponential backoff, circuit breakers, bulkheads, graceful degradation, idempotency, caching, health checks, load shedding, and observability.

Short Interview Answer (30-60 seconds)

At a high level, I would design the API so one slow dependency cannot bring down the whole request path. Requests move through edge protection, a load balancer, the API gateway, and then the Business Service. Every outbound call uses deadlines, bulkheads, a local circuit breaker, bounded retries, per-attempt timeouts, and exponential backoff with jitter. The service can use cached data, partial responses, or asynchronous processing when safe. The trade-off is more operational complexity and sometimes slightly higher latency.

Detailed Explanation

The goal is to keep the API useful when a dependency becomes slow or unavailable. The main challenge is preventing one failure from spreading across the whole system. I would explain the design by following the request path shown in the diagram.

Useful Questions to Ask the Interviewer
  1. Which clients and core use cases must the API support?
  2. What authentication, authorization, and data-validation rules should I assume?
  3. What scale, error handling, idempotency, and versioning requirements matter?
How would you design a fault-tolerant API? diagram
How to Explain It in an Interview
1. Start with the main request path

The request begins from a mobile app, web app, or third-party client. It first passes through DNS, the CDN, the WAF, and DDoS protection. These edge systems block harmful traffic and reduce unnecessary load.

The request then reaches the global or regional load balancer. The load balancer sends it to a healthy API Gateway instance. The gateway handles authentication, authorization, request validation, rate limiting, load shedding, idempotency keys, and correlation IDs.

Load shedding means rejecting extra work before the system becomes unstable. The gateway may return 429 when a client exceeds a limit. It may return 503 when the system cannot safely accept more work.

2. Process the request in the Business Service

The API Gateway forwards valid requests to the Business Service. This service owns the business logic. It also decides whether the request needs cached data, another internal service, an external provider, or asynchronous processing.

The Business Service checks the distributed cache when cached data is useful. A valid cache hit can avoid a slower dependency call. On a cache miss or expired value, the service calls the required dependency.

The service may call User Service, Payment Service, Inventory Service, or an External API. User Service owns User DB. Payment Service owns Payment DB. Inventory Service owns Inventory DB. The third-party provider is accessed only through its external API.

3. Protect every outbound dependency call

Every outbound call from the Business Service uses a resilience policy. The overall request deadline limits the total request time. A per-attempt timeout limits each individual dependency call.

A bulkhead limits concurrent calls to one dependency. This prevents a failing service from consuming every connection or worker. A local circuit breaker watches recent failures. It fails fast when the dependency appears unhealthy.

Retries are bounded. The service retries only safe or idempotent operations. An idempotent operation can be repeated without causing the action twice. Write requests can use an idempotency key to prevent duplicate processing.

Retries are used only for transient failures. The service waits using exponential backoff with jitter. The delay grows after each failure, while jitter adds randomness. This reduces retry storms. All retries must remain inside the overall deadline.

4. Degrade gracefully when possible

The Business Service should not fail the complete request when optional data is unavailable. It may return stale cached data when that data is still safe. It may also return static fallback data.

For optional fields, the service can return a partial response with warnings. A useful degraded response can still return 200. The response should clearly identify unavailable fields so the client does not treat missing data as complete data.

Some write operations can be queued for later. The service publishes an event to the message broker and returns 202 Accepted. The response should include an operation identifier or status URL when supported.

The broker uses at-least-once delivery. Therefore, consumers such as email workers and analytics workers must be idempotent. When an essential dependency is unavailable and no safe fallback exists, the API fails fast with 503.

5. Monitor health and failures

Every component sends metrics, logs, and traces to the observability systems. The correlation ID connects events from the gateway, Business Service, and dependencies.

Important metrics include latency, traffic, errors, saturation, retries, timeouts, circuit-breaker state, and cache hit ratio. Dashboards show system behavior. Alerts notify the team when thresholds are crossed.

Liveness checks show whether a process is running. Readiness checks show whether an instance should receive traffic. Configuration, secrets, feature flags, and service routing belong to the health and control plane.

6. Explain the trade-off

The benefit is better availability and controlled failure. A slow dependency is less likely to cause a complete outage. The downside is more configuration, monitoring, testing, and operational work. Retries may also increase dependency load when configured badly. I would accept this complexity because predictable degradation is safer than uncontrolled cascading failure.

Practical Complexity & Trade-offs

The benefit of this design is that one failing dependency does not automatically break the whole API. Timeouts stop calls from waiting forever. Bulkheads protect connections and workers. Circuit breakers stop repeated calls to an unhealthy service. Bounded retries can recover from short network problems. Backoff and jitter reduce retry storms. Caching improves speed and can provide safe fallback data. Load shedding protects the system during heavy traffic. The downside is additional code, configuration, and monitoring. Retry rules must be tested carefully because retries can increase load. Partial responses also make the client contract more complex. We accept these costs because the API remains predictable during failures.

Why Interviewers Ask This

Interviewers ask this question to test engineering judgment rather than memorized definitions. They want to see whether the candidate can control cascading failures, define clear service boundaries, and choose safe fallback behavior. They also evaluate correct use of timeouts, retries, idempotency, caching, load shedding, status codes, health checks, and observability. A strong answer explains both availability benefits and operational trade-offs.

Interviewer may ask next
What would you change if the Payment Service became slow during peak traffic?

I would protect the Payment Service without changing the rest of the architecture. The Business Service would keep a strict overall request deadline and a shorter per-attempt timeout for payment calls. A dedicated bulkhead would limit payment concurrency, so slow payment requests could not consume every worker or connection. The local circuit breaker would open when payment failures or timeouts cross the configured threshold.

I would avoid broad retries because payment operations can create duplicate charges. A retry would happen only when the operation uses an idempotency key and the failure is classified as transient. The retry must remain inside the request deadline.

If immediate payment confirmation is essential, the API should fail fast with 503 when no safe result is available. It should not pretend that payment succeeded. If the business contract supports delayed processing, the API can return 202 and queue the operation with an operation ID. The downside is that strict limits may reject some requests during a temporary slowdown, but this protects the wider system from cascading failure.

How would you keep asynchronous consumers correct when the message broker delivers the same event more than once?

I would make every consumer idempotent because the broker provides at-least-once delivery. Each event should include a unique eventId, event type, version, occurrence time, correlation ID, and payload. Before applying a side effect, the consumer checks whether that eventId was already processed.

For example, the Email Worker should not send the same message twice. It can store the processed eventId with the result of the first operation. When the same event arrives again, the worker acknowledges it without repeating the email.

The consumer should acknowledge the broker message only after successful processing. Temporary failures can use bounded retries. Repeated failures can move the event to a dead-letter path for investigation. Logs and traces should include the eventId and correlation ID.

The main downside is extra storage and cleanup for processed event records. There is also more consumer logic. However, this is required because the design does not claim exactly-once delivery.

117. What is FastAPI?NEWAPI DesignEasy

Question Details

Define FastAPI as a Python framework for building web APIs using standard type hints. Explain path operations, request parsing, validation, response models, dependency injection, automatic OpenAPI documentation, async endpoint support, ASGI serving, exception handling, and the distinction between FastAPI, an ASGI server such as Uvicorn, and the application business logic.

Short Interview Answer (30-60 seconds)

At a high level, FastAPI is a Python framework for building web APIs with standard Python type hints. A client sends a request to FastAPI. FastAPI parses and validates the data, resolves dependencies, runs the path operation, validates the response model, and sends JSON back. It also creates OpenAPI documentation, supports async endpoints, and handles API exceptions. Uvicorn is the ASGI server that runs the FastAPI application, while my code contains the business logic. The main trade-off is learning framework concepts in return for clear validation, reusable dependencies, and less repeated API code.

Detailed Explanation

This question asks what FastAPI is and what work it does for a web API. The goal is to build an API without manually handling every common task. A client sends some data and expects a clear response. FastAPI helps check that data, call the correct function, and prepare the result. The main challenge is understanding which work belongs to FastAPI, which work belongs to the server, and which work belongs to our own code. I would explain the same request flow shown in the diagram, from client request to JSON response.

Useful Questions to Ask the Interviewer
  • Do you want only a FastAPI definition, or also the full request flow?
  • Should I explain the difference between FastAPI and Uvicorn?
  • Would you like me to walk through the example POST /items/ path operation?
What is FastAPI? diagram
How to Explain It in an Interview
1. Start with what FastAPI provides

I would start by saying FastAPI is a Python framework for building web APIs. It uses standard Python type hints to understand expected data types. Those type hints help FastAPI parse input, validate values, shape responses, and generate documentation. This reduces repeated API code and makes the API contract easier to understand. FastAPI creates an ASGI application object, but it does not replace the server that accepts network connections.

2. Follow the request from the client

The request first comes from a browser or another API client. It reaches the FastAPI application and matches a path operation. A path operation is a Python function connected to an HTTP method and path. The diagram shows POST /items/ connected to create_item. FastAPI can read path values, query values, headers, and request bodies. It then checks them against Python type hints and Pydantic models before the endpoint function runs.

3. Resolve dependencies and run the path operation

Before calling the endpoint, FastAPI can resolve reusable dependencies with Depends(). The example uses Depends(get_token). The diagram shows dependencies being useful for database sessions, authentication, services, and settings. After those dependencies are available, FastAPI runs the path operation. The endpoint then performs the application work. That business logic belongs to our code. It may include services, database operations, authentication, authorization, or other application rules shown in the diagram.

4. Handle errors and create the response

FastAPI provides exception handling for expected API errors. The example checks whether the token equals valid-token. If it does not, the endpoint raises HTTPException with status code 401 and detail Unauthorized. When the operation succeeds, it returns an Item. The path operation declares response_model=Item. FastAPI uses that response model to validate and shape the returned data. It then serializes the response to JSON and sends it back to the client.

5. Explain automatic documentation and async endpoints

FastAPI creates an OpenAPI schema from the application code. The diagram also shows interactive API documentation at /docs. This is useful because the documentation comes from the same routes and models used by the application. FastAPI also supports async def and await. Async endpoints are helpful when code spends time waiting for input-output work. While one request waits, the server can continue working with other connections.

6. Separate FastAPI, Uvicorn, and business logic

I would finish by separating the three responsibilities clearly. FastAPI is the framework. It defines routes and models, parses and validates data, injects dependencies, creates OpenAPI documentation, and handles exceptions. Uvicorn is an ASGI server. It runs the FastAPI application, handles network connections, and manages concurrency and workers. The diagram runs the app with uvicorn main:app --reload. Business logic is our own code. It contains endpoint behavior, services, database operations, authentication, authorization, and other application rules. So the client sends a request, FastAPI processes it, our code performs the work, and FastAPI returns the JSON response.

Practical Complexity & Trade-offs

The benefit of FastAPI is that many common API tasks are built into one framework. Type hints and Pydantic models make request and response rules clear. Dependency injection makes shared code easier to reuse and test. Automatic OpenAPI documentation reduces manual documentation work. Async support helps when endpoints spend time waiting on input-output operations. The downside is that developers must learn FastAPI concepts such as path operations, response models, dependencies, and ASGI. Uvicorn is also a separate server component that must be understood and operated. Validation adds useful checks, but it also adds some processing. We accept this because it gives clearer API contracts, fewer manual checks, reusable components, and easier maintenance.

Why Interviewers Ask This

Interviewers ask this to see whether you understand FastAPI beyond a simple definition. They want to hear how path operations, request validation, response models, dependencies, async endpoints, documentation, and exception handling fit together. They also check whether you separate responsibilities correctly. FastAPI defines and processes the API. Uvicorn runs the ASGI application. Your code owns the business logic. A strong answer shows clear API boundaries, correct request and response flow, and sensible framework trade-offs.

Interviewer may ask next
What changes if this FastAPI application must handle many slow network operations at the same time?

I would keep the same overall FastAPI design, but I would use async path operations where the code spends time waiting. The affected part is the endpoint function and the business logic it calls. I would define those operations with async def and use await for supported input-output work. FastAPI would still parse and validate the request first. It would still resolve dependencies before running the path operation. The response model would still validate and shape the returned data. Uvicorn would still run the ASGI application and manage concurrent connections. The main benefit is that one worker can continue handling other connections while one request waits. This can improve concurrency for network-heavy work. The downside is that async code adds another programming model to understand. It also does not make CPU-heavy work faster by itself. I would therefore use async where waiting is the real bottleneck, while keeping the rest of the design unchanged.

How would you explain the difference between FastAPI, Uvicorn, and the application business logic?

I would separate them by responsibility. FastAPI is the framework that defines path operations and handles API-level work. It parses request data, validates types and Pydantic models, resolves dependencies, handles expected exceptions, validates response models, and creates OpenAPI documentation. Uvicorn is the ASGI server. It runs the FastAPI application, accepts network connections, and manages concurrency and workers. The business logic is our own application code. It decides what the endpoint actually does, such as calling services, performing database operations, or applying authentication and authorization rules shown in the diagram. The request reaches the FastAPI application through the server. FastAPI prepares the validated inputs and calls the endpoint. The business logic performs the work and returns data. FastAPI then validates and serializes that result before the client receives JSON. The benefit is clear ownership. The downside is that developers must understand several layers, but each layer has a focused job.

118. What is middleware in a Python web API?NEWAPI DesignEasy

Question Details

Define middleware as code that wraps request handling so it can inspect or change an incoming request, call the next handler, and inspect or change the response. Explain ordering, short-circuiting, exception boundaries, and common uses such as request IDs, logging, timing, CORS, authentication, and compression. Relate the concept to ASGI or FastAPI without making it framework-specific.

Short Interview Answer (30-60 seconds)

At a high level, middleware is code that wraps my API request handling. The client request passes through middleware before reaching the route handler. Each layer can inspect or change the request, call the next handler, or stop early. After the route creates a response, the response returns through the middleware in reverse order. Common uses include request IDs, logging, timing, authentication, CORS, compression, and rate limiting. The benefit is reusable shared behavior. The trade-off is that ordering and error handling become more important.

Detailed Explanation

Middleware is helper code around normal API request handling. It lets us put common work in one place instead of repeating it inside every route. In this diagram, the client request moves through several middleware layers before reaching the route handler. A layer can inspect the request, change it, continue processing, or stop early. After the route produces a response, that response travels back through the middleware in reverse order. The main challenge is keeping this order clear while handling shared work and errors safely.

Useful Questions to Ask the Interviewer
  • Should I explain middleware mainly as a general web API concept?
  • Should I also relate the idea to ASGI and FastAPI?
  • Should I cover ordering, early responses, and exception handling?
What is middleware in a Python web API? diagram
How to Explain It in an Interview
1. Start with the basic idea

I would start by saying that middleware wraps request handling. The client sends a request toward the API. Before the Route Handler runs, the request passes through the middleware stack.

Each middleware can inspect or change the incoming request. It can also perform shared work that many routes need. This keeps that work outside the endpoint function or view.

2. Follow the request through the stack

In this diagram, the request moves from Middleware 1 to Middleware 2 and then Middleware N. The exact stack order depends on how an application builds its middleware chain, but this diagram clearly shows that request order.

Middleware 1 represents Request ID and Logging work. A request ID helps track one request across processing. Logging records useful request or response information.

Middleware 2 represents an Authentication Check. Authentication means checking who the caller is. If processing should continue, this layer calls the next handler.

Middleware N represents another shared concern, such as Compression or CORS. CORS means rules that control browser requests coming from another web origin.

3. Explain short-circuiting

A middleware does not always have to call the next handler. It may return a response early and stop the chain. This behavior is called short-circuiting.

For example, an authentication layer may stop a request that should not continue. In that case, later middleware and the Route Handler do not process that request. This avoids unnecessary work and keeps shared checks outside route code.

4. Explain the route and response path

If every middleware continues, the request reaches the Route Handler. The handler runs the endpoint function or view and produces the API response.

The response then travels back through the middleware in reverse order. Middleware N sees the returning response before Middleware 2, and Middleware 1 is one of the outer layers before the response reaches the Client.

This reverse path lets middleware perform work after downstream processing. Timing middleware can measure elapsed time. Logging can record completion information. Compression middleware can compress the response body before it is sent.

5. Explain exception boundaries

Middleware can also create an exception boundary around later processing. An exception is an unexpected error while handling the request.

The diagram's ASGI-style example calls the next application inside a try block. If downstream processing raises an exception, that middleware can catch it and send an error response. This keeps the error-handling decision around the wrapped application instead of repeating it in every route.

6. Relate the idea to ASGI and FastAPI

ASGI is a standard interface used by Python web applications and servers. An ASGI middleware can itself behave like an ASGI application while wrapping another ASGI application.

The diagram's SimpleMiddleware stores the next application in self.app. Its __call__ method receives scope, receive, and send, performs work before the next application, and then calls await self.app(scope, receive, send).

For real response inspection or modification at the ASGI message level, middleware commonly wraps the send callable so it can observe outgoing response messages. FastAPI is built on ASGI, so this same middleware concept applies there without being specific to FastAPI.

7. Finish with common uses and the trade-off

I would finish with the common uses shown in the diagram: Request IDs, Logging, Timing or Metrics, Authentication, CORS, Compression, and Rate Limiting.

The benefit is reuse and cleaner route handlers. The downside is added request processing and less obvious control flow. Ordering matters because an outer middleware may need to observe work performed by inner layers. Keeping each middleware focused on one clear job makes the design easier to understand.

Practical Complexity & Trade-offs

The main design choice is deciding what belongs in middleware and where each layer sits. The benefit is reuse. Request IDs, logging, timing, authentication, CORS, compression, and rate limiting can work across many routes without repeated code. The downside is extra processing for every request that passes through those layers. Ordering also matters. The request moves through middleware toward the Route Handler, while the response returns through those layers in reverse order. Short-circuiting can stop unwanted work early. Exception boundaries can handle errors from later processing. This is useful, but too many middleware layers can make debugging harder. We accept that trade-off because shared behavior stays separate from normal route code.

Why Interviewers Ask This

Interviewers ask this question to test whether you understand the complete API request and response path. They want more than a definition. They look for correct reasoning about middleware ordering, calling the next handler, short-circuiting, reverse response flow, and exception handling. They also want to see whether you can choose good middleware responsibilities, such as logging, authentication, timing, CORS, compression, and request IDs, while keeping route handlers focused on their main work.

Interviewer may ask next
What happens if authentication middleware rejects a request before it reaches the route handler?

The authentication middleware can stop the request and return a response without calling the next handler. This is short-circuiting. In the diagram, the request reaches Middleware 2 after passing through Middleware 1. Middleware 2 performs the Authentication Check. If that layer decides processing should stop, Middleware N and the Route Handler do not receive the request.

The response then travels back through the middleware layers that already wrapped the call. This means an outer layer, such as Request ID or Logging middleware, can still observe that the request finished early if its implementation is designed to do so.

The benefit is that rejected requests do not waste work in later layers or route code. It also keeps a shared authentication check outside individual routes. The downside is that middleware ordering becomes important. If logging must record rejected requests, the logging layer must wrap the authentication layer. The rest of the request and response design remains unchanged.

How do timing and compression middleware work when the response comes back?

Timing and compression both wrap downstream processing, but they do different jobs. Timing middleware can record a start time before it calls the next handler. After downstream processing finishes, it calculates the elapsed time and records that measurement. This is why timing naturally works around the request and response flow.

Compression middleware mainly affects the outgoing response. The request passes through it toward the Route Handler. When response data comes back, the middleware can compress the response body before the Client receives it. In a raw ASGI implementation, response-aware middleware commonly wraps the send callable so it can observe or change outgoing response messages.

Correctness depends on preserving the middleware order shown by the stack. Requests move inward toward the Route Handler, and response handling moves outward in reverse order. The benefit is reusable response processing outside route functions. The downside is extra CPU work and more middleware behavior to understand when debugging.

119. How would you secure communication between microservices?API DesignHard

Question Details

Design secure service-to-service communication for Python APIs. Explain workload identity, mutual TLS, token validation, authorization, certificate rotation, secret management, replay protection, network policies, audit logging, and how trust is maintained across environments.

Short Interview Answer (30-60 seconds)

At a high level, my goal is to allow only trusted services to communicate. I would separate the design into workload identity, short-lived credentials, encrypted transport, request authorization, and audit logging. Service A gets a trusted identity and a short-lived JWT. It then calls Service B through the two service-mesh proxies using HTTPS, mTLS, and the bearer token. Service B validates the token and permissions before processing the request. The response returns from Service B through the B-side proxy and A-side proxy to Service A. The trade-off is stronger security with more operational complexity.

Detailed Explanation

The goal is to secure every call between Service A and Service B. The main challenge is proving both service identities while also checking whether the caller may perform the requested action. The diagram solves this with workload identity, short-lived certificates, OAuth tokens, mTLS, authorization rules, network controls, and audit logging.

Useful Questions to Ask the Interviewer
  1. Which clients and core use cases must the API support?
  2. What authentication, authorization, and data-validation rules should I assume?
  3. What scale, error handling, idempotency, and versioning requirements matter?
How would you secure communication between microservices? diagram
How to Explain It in an Interview
1. Start with the security goal

I would begin by saying that network location is not enough to trust a service. Every workload must prove its identity before making or accepting a call. The design therefore uses two checks. Mutual TLS authenticates the communicating workloads and encrypts the connection. The JWT carries the caller's application identity, audience, scopes, and other claims used by Service B.

Both checks must succeed. mTLS does not decide whether Service A may perform a business action. The token alone also does not protect traffic while it moves across the network.

2. Establish workload identity

The Workload Identity system checks Service A and Service B. It then gives each workload a trusted SPIFFE identity or OIDC subject. This identity represents the running service instead of a person or shared password.

The Certificate Authority uses this trusted identity to issue short-lived X.509 or SPIFFE certificates. It provides one certificate to the A-side proxy and another to the B-side proxy. These certificates rotate automatically. The proxies reload them without requiring manual key changes.

Separate environments use different trust domains, certificate authorities, issuers, policies, and keys. Development workloads therefore cannot automatically become trusted production workloads.

3. Obtain the access token

Before calling Service B, Service A sends a token request to the Authorization Server. The request uses Service A's workload identity through client credentials or token exchange. The Authorization Server verifies that identity before issuing a short-lived JWT.

The token is restricted to Service B through its audience claim. It also contains the scopes or claims needed for authorization. The Authorization Server publishes JWKS, which is a set of public keys used to verify the token signature. Service A attaches the JWT as a bearer token when making the service call.

4. Send the request through mutual TLS

Service A uses its Python client, such as requests or httpx, to call Service B. The request first reaches the A-side proxy. It then travels to the B-side proxy over HTTPS with mTLS and the bearer JWT.

The A-side proxy verifies Service B's certificate. The B-side proxy verifies Service A's certificate. This mutual check proves both workload identities and encrypts the traffic. Network Policies also allow only the required Service A to Service B path. All other traffic is denied by default.

If mTLS verification fails, the connection is rejected before the business request reaches Service B.

5. Validate and authorize the request

After the B-side proxy accepts the secure connection, Service B validates the JWT. It checks the signature using JWKS. It also checks the issuer, audience, expiration time, not-before time, token identifier, and required scopes.

An invalid or expired token returns 401. A valid token proves the caller's identity, but Service B must still authorize the request. It uses RBAC or ABAC rules to decide whether the caller may perform the action. A denied authorization decision returns 403.

For sensitive one-time operations, replay protection may check a nonce or token identifier against a replay cache. Write operations may also use idempotency keys so the same retried request does not create duplicate work.

6. Process the request and return the response

After authentication and authorization succeed, Service B processes the request. Its FastAPI application returns the shown success or error response. The response may use JSON or Protobuf.

The response direction is the reverse of the request. It moves from Service B to the B-side proxy, then to the A-side proxy, and finally back to Service A. The response remains protected by the established mTLS connection.

Service A handles the returned result or error. It does not treat audit logging as part of the business response path.

7. Explain secrets, logging, failures, and trade-offs

The Secret Manager stores application secrets such as database credentials, API keys, and encryption keys. It is not the normal source of the short-lived workload certificates used by the proxies.

Service A, Service B, and the proxies send audit events, traces, and metrics to the Observability and Audit system. This creates a record of service calls, identity checks, authorization decisions, and failures.

If the Authorization Server is unavailable, it does not issue new tokens. Existing valid tokens may continue until they expire. Service B may use previously validated JWKS only within the configured cache lifetime. If no valid signing key is available, validation fails closed. The main trade-off is that this design greatly reduces trust risk, but it requires certificate rotation, token management, policy management, monitoring, and reliable identity infrastructure.

Practical Complexity & Trade-offs

The benefit is that one stolen password is not enough to enter the system. Each service gets its own short-lived identity, certificate, and access token. mTLS protects the connection, while the JWT and authorization rules control the requested action. This is safer, but it adds more systems to operate. The team must maintain the identity provider, Authorization Server, Certificate Authority, proxies, policies, and audit tools. Short-lived credentials reduce the damage from a stolen key, but they must rotate reliably. Default-deny network rules reduce unwanted access, but incorrect rules can block valid traffic. We accept this complexity because service identity, encryption, least privilege, and audit records are important security controls.

Why Interviewers Ask This

The interviewer wants to see whether the candidate understands that secure communication needs several separate controls. A strong answer distinguishes workload identity, transport encryption, token validation, and business authorization. It also shows correct ownership between services, proxies, identity systems, certificate authorities, and audit tools. The interviewer is also checking failure handling, short-lived credential rotation, replay protection, network restrictions, and whether the candidate can explain security trade-offs without claiming perfect protection.

Interviewer may ask next
What happens if the Authorization Server becomes unavailable while services are still running?

I would fail closed for new token issuance, but I would not immediately stop every existing call. The Authorization Server would stop issuing new JWTs because it cannot safely verify and sign new requests. Service A could continue using an already-issued token only until that token expires.

Service B would still validate every token. It would check the signature, issuer, audience, time claims, and scopes. It could use previously validated JWKS from its cache, but only within the configured cache lifetime. If the required public signing key is missing or no longer valid, Service B must reject the request instead of bypassing validation.

The mTLS connection can still prove the workload identities, but mTLS does not replace the missing business authorization token. The team should monitor token issuance failures and restore the Authorization Server quickly. The main downside is that short token lifetimes improve security but give the team less time to recover before valid service calls begin failing.

How would you prevent a captured service request from being replayed?

I would keep the same mTLS and JWT design, but add stronger protection for sensitive operations. TLS protects the request while it travels across the network. The JWT should also have a short lifetime and a narrow audience so it cannot be reused broadly.

For a sensitive one-time action, Service A can include a nonce or unique request identifier. Service B checks that value against a replay cache. If the same identifier appears again during the allowed time window, Service B rejects the duplicate request. Merely checking that the JWT contains a jti claim is not enough. The server must remember which values were already used.

For write operations that may be retried normally, I would use an idempotency key. Service B stores the previous result for that key and returns the same result instead of repeating the write. The downside is extra storage and cleanup work for replay records and idempotency keys.

120. What is profiling in Python?NEWPerformanceEasy

Question Details

Define profiling as measuring where a running Python program spends time and resources. Explain deterministic profiling with cProfile, sampling profilers, wall time versus CPU time, function call counts, memory and allocation measurement, I/O waits, representative inputs, baselines, and why optimization should target a measured bottleneck and be verified with the same workload.

Short Interview Answer (30-60 seconds)

I would first measure the program with a representative workload and save a baseline. Profiling means finding where a running Python program spends time and resources. I can use cProfile for deterministic function call timing in a controlled run, or a sampling profiler when I need lower overhead on a running process. I would compare wall time, CPU time, call counts, memory and allocation data, and input and output waits, then optimize only the measured bottleneck and profile again with the same workload. The tradeoff is that detailed profiling can add overhead, while sampling gives an estimate.

Detailed Explanation

I start by measuring the same real work that users or jobs normally do. I record how long it takes and how much computer power and memory it uses. Then I look for the part that takes the most time or uses the most resources. I do not guess. I change only the measured slow part, run the same work again, and compare the result with the first measurement. This keeps the test fair and helps me see whether the change really helped without moving the problem somewhere else.

Useful Questions to Ask the Interviewer
  1. Are we profiling a local program, a service request, or a background job?
  2. Is the main problem slow response time, high CPU use, high memory use, or waiting for input and output?
  3. Can we reproduce the issue with representative inputs and the same environment?
  4. Do we need low overhead observation of a running process, or can we use a controlled profiling run?
What is profiling in Python? diagram
How to Explain It in an Interview

Profiling is the process of measuring where a running Python program spends time and resources. I first define the symptom and measurement boundary. For example, I may measure one representative program run from start to finish, including its normal input and output waits. I save a baseline before changing code.

Wall time is the real elapsed time from start to finish, so it includes waiting. CPU time is the time the CPU spends executing code, so waiting time is excluded. Function call counts show how often functions run. Memory and allocation profiling shows where Python memory is used and where objects are created. Input and output wait time shows time spent waiting for files, network calls, databases, or other external work.

For deterministic profiling in a controlled run, I can use cProfile. It records Python function calls and timing, which is useful for finding functions with high total time or cumulative time. Its main limitation is overhead because it observes function calls directly. For lower overhead observation of a running Python process, I can use a sampling profiler such as py spy. It takes periodic snapshots, so it estimates where time is spent and can miss very short events.

No single profiler measures everything. cProfile is not a memory allocation profiler. For Python allocation tracing, tracemalloc can compare snapshots and show where Python allocations come from, but it does not track every native allocation. Application metrics and traces can also help separate Python execution from database, network, queue, lock, or event loop waiting when those parts are inside the measurement boundary.

I use representative requests, jobs, data sizes, and dependency behavior. I do not treat one profiler run or one small timing test as final proof. After the evidence identifies the real bottleneck, I make one focused change. Then I rerun the same representative workload and compare with the baseline. I check the same timing and resource measures, verify that the program output is still correct, and confirm that the bottleneck was reduced instead of moved to another part of the system. After deployment, I continue watching the same production metrics when production monitoring is available.

Technical Approach
  1. Define the symptom and measurement boundary, such as total elapsed time, CPU use, memory use, or input and output waiting for one representative run.
  2. Capture a baseline before changing code.
  3. Reproduce the same workload with representative inputs and dependency behavior.
  4. Use the right evidence source. Use cProfile for deterministic function call timing in a controlled run, a sampling profiler for lower overhead observation, and a memory allocation profiler when memory is the problem.
  5. Compare wall time, CPU time, function call counts, memory and allocation data, and input and output waits to classify the bottleneck from evidence.
  6. Change only the measured bottleneck.
  7. Run the same workload again and compare with the baseline.
  8. Verify correct output and check that the bottleneck did not move elsewhere.
  9. Monitor the same important metrics after deployment when production monitoring is available.
Practical Insights

Profiling has a cost. cProfile adds extra work because it records function calls, so the measured run can be slower than normal. A sampling profiler usually has lower overhead, but it gives an estimate and may miss very short work. Memory tracing also uses extra memory and CPU. The test itself takes time because the before and after workloads should be the same and representative. The optimization may also trade one resource for another, such as using more memory to reduce CPU work, so I compare the full set of relevant measurements after the change.

Why Interviewers Ask This

Interviewers ask this to see whether I measure before I optimize. They want to know if I can separate real elapsed time, CPU work, function calls, memory use, allocations, and waiting for input and output. They also want to see whether I choose a suitable profiler, understand its limits, use representative inputs, create a baseline, and verify a change with the same workload.

Common interview mistakes

Common mistakes are optimizing before measuring, profiling unrealistic input, comparing different workloads before and after a change, confusing wall time with CPU time, treating cProfile as a memory profiler, assuming one profiler explains every delay, trusting one sample as final proof, using a small timing experiment as proof of whole service performance, ignoring database or network waiting, and forgetting to verify correct output after optimization. Another mistake is improving one function while moving the bottleneck to memory, input and output, or another dependency.

Interview tip

Explain profiling as a measurement loop. Start with the symptom, save a baseline, use representative input, choose the profiler that answers the right question, find the measured bottleneck, change that part, and verify with the same workload. Mention that cProfile gives detailed function timing with overhead, while sampling gives a lower overhead estimate.

Interviewer may ask next
What if wall time is high but cProfile shows little CPU time?

That usually means the measured workload may be spending much of its time waiting rather than executing Python code. For the same representative program run, I would keep the start to finish wall time boundary and inspect input and output waits such as files, network calls, database work, queues, or other blocking operations. cProfile function timing alone may not explain an external wait, so I would combine it with application timing, tracing, or dependency metrics. The key tradeoff is adding enough instrumentation to locate the wait without adding so much overhead that it changes the workload.

When would you choose a sampling profiler instead of cProfile?

I would choose a sampling profiler when I need lower overhead observation of the same running Python workload, especially when stopping the process for a controlled cProfile run is not practical. The measurement boundary stays the same representative process and workload, but the sampling profiler takes periodic snapshots instead of recording every Python function call. This matters because it usually disturbs the process less. The tradeoff is that the result is an estimate and very short functions may be missed, so I still verify any optimization with the same workload and baseline.

More questions load as you scroll

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.