Design a Resilient Bootstrap API Aggregator
DoorDashSoftware Engineer · Technical ScreenLast updated
Design a resilient bootstrap aggregation service that fetches critical initial state for a mobile app on launch. Tests interface design, concurrent I/O, partial failure handling, and operational trade-offs.
Scenario
When a customer launches the consumer app, the client triggers a single "bootstrap" request to hydrate its initial state. A slow or failing bootstrap directly degrades the app's launch experience.
Your task is to design the core aggregation layer for GET /v1/bootstrap?user_id={userId}. The aggregator fetches data concurrently from four downstream internal services:
- User Profile Service (Critical): Name, email, saved default address.
- Active Order Service (Non-critical): Live order tracking status.
- Cart Service (Non-critical): Persisted unsubmitted items in the user's cart.
- Experimentation Service (Non-critical): Feature flags and UI experiment variants.
Requirements
1. Interface & Data Models
Define the data contracts for the response and the aggregator interface. Each aggregated domain in the response must indicate its status (SUCCESS, DEGRADED, or FAILED) alongside its payload or fallback.
from dataclasses import dataclass
from typing import Optional, Dict, Any, List
from enum import Enum
class SectionStatus(Enum):
SUCCESS = "SUCCESS"
DEGRADED = "DEGRADED"
FAILED = "FAILED"
@dataclass
class AggregatedSection:
status: SectionStatus
data: Optional[Dict[str, Any]] = None
error_code: Optional[str] = None
@dataclass
class BootstrapResponse:
user_id: str
profile: AggregatedSection
active_order: AggregatedSection
cart: AggregatedSection
experiment_flags: AggregatedSection
class BootstrapAggregator:
def __init__(
self,
profile_client: Any,
order_client: Any,
cart_client: Any,
experiment_client: Any,
timeout_ms: int = 300
):
...
async def get_bootstrap_data(self, user_id: str) -> BootstrapResponse:
...
2. Failure & Resilience Rules
- Critical Dependencies: If the
UserProfileServicefails (e.g., timeout, 5xx, or unauthenticated), the entire bootstrap call must fail and return an appropriate error (e.g., HTTP 502/504). - Non-Critical Dependencies: If
ActiveOrderService,CartService, orExperimentationServicetimes out or throws an error, returnSectionStatus.DEGRADED(with safe defaults such as empty lists or local default flags) orSectionStatus.FAILED. The overall bootstrap request must still return HTTP 200. - Bound Latency: Downstream calls must run concurrently. Enforce a global timeout (e.g., 300ms) and individual task timeouts.
3. Edge Cases & Operational Invariants
Describe or implement:
- How to handle context cancellation if the client disconnects prematurely.
- Fallback strategies for experimentation (e.g., static local fallback config vs. returning empty).
- Logging, metrics, and alerting to detect downstream degradation before users report it.
Example Behavior
Scenario: Active Order Service times out
{
"user_id": "u_12345",
"profile": {
"status": "SUCCESS",
"data": { "name": "Jane Doe", "default_address_id": "addr_99" }
},
"active_order": {
"status": "DEGRADED",
"data": null,
"error_code": "DOWNSTREAM_TIMEOUT"
},
"cart": {
"status": "SUCCESS",
"data": { "item_count": 2, "subtotal_cents": 2450 }
},
"experiment_flags": {
"status": "SUCCESS",
"data": { "new_checkout_flow": true }
}
}
Hints
Hint 1
Differentiate between critical and non-critical dependencies early so your concurrency orchestration can abort early on critical failures.
Hint 2
Use asynchronous concurrency primitives (such as `asyncio.gather` with `return_exceptions=True` or `asyncio.wait`) alongside explicit timeouts to avoid head-of-line blocking.
Hint 3
Ensure each section in the response contract contains both a payload and an error/status metadata wrapper to allow the mobile client to render degraded UI states seamlessly.
Follow-up questions
- How would you integrate circuit breakers (e.g., using Netflix Hystrix or resilient bulkhead patterns) to protect downstream services during a major incident?
- How would you handle caching for this endpoint given that the user profile changes rarely, but active orders change every few seconds?
- If mobile network latency is high, how could you evolve this endpoint using streaming protocols (like Server-Sent Events or gRPC) rather than a single blocking JSON payload?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.