Reviewed by 6 specialized AI reviewers. Explore the diagram and the full per-section feedback below.
Loading diagram…
This is a decent mid-level design with solid instincts around service decomposition, consistency, caching, and reservation semantics. The main gaps are in completeness and precision rather than fundamentally poor choices: the candidate needs to better connect the serving path, make the API and workflow more explicit, and tie sizing back to the given assumptions.
Consistency called out for critical write paths
The design correctly identifies inventory management and payments as areas that need stronger consistency. That is a solid NFR choice because overselling inventory or double-processing payment would directly violate correctness for ordering.
Search latency target is explicitly stated
Providing a concrete latency goal for search (<500ms) is useful and appropriate for this problem. It gives a measurable performance target for the availability lookup path instead of leaving responsiveness vague.
Eventual consistency tradeoff is acknowledged for search
Allowing eventual consistency on the search/read path is a reasonable NFR tradeoff here. It shows awareness that availability queries can often tolerate slightly stale data in exchange for lower latency and better scalability, as long as ordering uses stronger correctness checks.
Availability target is missing
The NFRs say the system should be highly scalable, but they do not define an availability objective such as 99.9% or 99.99% for search and order placement. Without an explicit uptime target, it is hard to judge whether the design meets reliability expectations. Add concrete availability SLAs for the main user flows.
Consistency model is not precise enough
The design mentions strong consistency for inventory and payment and eventual consistency for search, which is directionally correct, but it does not specify the boundary between them. For example, search may show stale stock, but order placement must revalidate inventory atomically before confirming. State that final reservation/checkout uses strong consistency while browse/search can tolerate bounded staleness.
Scalability is stated qualitatively, not tied to assumptions
Saying the system must be highly scalable is too broad by itself. Since assumptions are given (100k items, 10k centers, 1M orders/day), it would be stronger to translate them into expected throughput or peak QPS targets for search and ordering so the NFRs are measurable.
Covers the main domain nouns
The entity list includes the core concepts needed for the stated requirements: users place orders, products are stocked in fulfillment centers, inventory connects product availability to a center, and orders represent purchases.
Basic scale numbers are too sparse
You included write and read QPS, which is a good start, but the capacity section is still too thin for this problem. Given the stated assumptions, it should also translate the 100k items and 10k centers into at least rough sizing for inventory/availability records or explain the expected lookup fanout. Add a few more back-of-the-envelope numbers such as peak QPS assumptions, total inventory entries, and rough storage size so the sizing feels methodical rather than just listing two throughput numbers.
QPS math is not clearly derived and appears inconsistent
1M orders/day is about 11.6 writes/sec on average, not 1.2K QPS. If you intended peak traffic, burst factor, or included multiple downstream writes per order, that needs to be stated explicitly. As written, the number looks off by roughly two orders of magnitude. Recompute from the assumptions and then, if needed, apply a clear peak multiplier such as 10x or 100x.
Ballpark may lead to over- or under-sizing
Because the write QPS estimate is not grounded in the stated assumptions, the resulting 12k read QPS may also be misleading. For a mid-level design, the important thing is not exact precision but showing a defensible ballpark tied to the given numbers. Start from 1M/day, convert to average QPS, state a peak factor, then derive reads from the 10:1 ratio.
Core customer flows are represented
The routes include a product search endpoint and order creation/read endpoints, which map to the two main functional requirements: checking item availability and placing an order.
Availability API does not clearly return 1-hour deliverability
The main requirement is to query items that are available and deliverable within 1 hour by location. `GET /products?keyword=&Lat=&Long=` suggests search by keyword and location, but it does not explicitly model availability status, nearby fulfillment center selection, or a 1-hour delivery filter in the response. A better design would either make this endpoint explicitly availability-focused (for example, returning only deliverable products with availability metadata) or add a dedicated availability route such as `/availability?product_id=&lat=&long=`.
Inventory lookup is not location-aware
`GET /inventories/{product_id}` is too limited for this use case because inventory depends on fulfillment center and customer location. Without location or center context, the API cannot determine whether the item is available from a nearby center and deliverable within 1 hour. Fix by including location parameters or center scoping, such as `/inventories/{product_id}?lat=&long=` or `/centers/{center_id}/inventories/{product_id}`.
Order request structure is error-prone
Using parallel arrays (`products` and `items`) can lead to mismatches and makes validation harder. A more robust API shape is a single list of line items, for example `items: [{ product_id: 123, quantity: 2 }]`, which is clearer and less likely to produce malformed requests.
REST resource naming is inconsistent with customer-facing scope
`POST /products` creates products, but product creation is not part of the stated functional requirements. It is not wrong to include it, but for this problem the more important missing detail is the customer-facing read contract for availability. If keeping admin-style product creation, consider separating admin and customer APIs clearly.
Response shapes are underspecified
The routes only say `-> Product`, `-> Inventory`, and `-> Order`, which makes it hard to verify whether the API returns the fields needed by clients, such as available quantity, estimated delivery window, fulfillment center used, order status, and line items. Adding example response payloads would make the design much stronger and easier to evaluate.
Read path separated from order path
Using Product service for availability queries and Order service for order placement is a solid high-level split. It keeps the high-read availability workload isolated from the write-heavy ordering workflow, which is appropriate for the stated scale.
Read replicas and cache support query scalability
Adding Postgres read replicas plus Redis for cached geo/latency lookups is a sensible architecture choice for handling frequent availability searches across many items and centers. This helps reduce load on the primary database.
Inventory hold concept is included
Modeling an inventory_hold table shows awareness that ordering needs a reservation step before final inventory deduction. That is an important architectural element for preventing oversell during payment processing.
End-to-end availability flow is not fully connected
The main requirement is to query item availability deliverable within 1 hour from nearby fulfillment centers, but the Product service is not connected to the source of inventory and center data in the diagram. It talks to read replicas, Redis, Google Maps, and Elasticsearch, but there is no clear path from Product service to inventory/shop records in Postgres or another inventory store. As drawn, the system cannot reliably answer availability by location. Fix this by explicitly connecting Product service to a read model containing inventory-by-center and center location data, either via read replicas or a dedicated inventory index.
User/API entry points are orphaned
Users, the load balancer/API gateway annotation, and the listed GET /products and POST /orders endpoints are not actually connected to Product service or Order service. That makes the design incomplete from a request-routing perspective. Add explicit connections from Users -> API gateway/load balancer -> Product service and Order service so the request path works end to end.
Order and payment interaction direction is unclear
The only connection shown is Payment service -> Order service with payment completion status, but the architecture does not show Order service initiating payment or how the order waits for payment before confirming inventory. This makes the ordering workflow ambiguous. A clearer design would show Order service creating the order and inventory hold, calling Payment service, then finalizing or releasing the hold based on the payment result.
Elasticsearch role in the availability flow is underspecified
Elasticsearch is connected to Product service, but there is no indication of what data is indexed there or how it stays in sync. For the stated requirements, search alone is not enough; the system also needs center-level availability and delivery eligibility. Clarify whether Elasticsearch stores product metadata only or a denormalized availability index, and show the ingestion/update path if it is part of the serving flow.
Redundancy is only partially addressed
Read replicas improve read scaling, but the write path appears to depend on a single Postgres primary with no visible failover strategy. At this scale, that may still work, but adding a note about primary-replica failover or managed HA Postgres would make the operational story more complete.
Draw your architecture for Food Delivery System and get an instant hire/no-hire signal from 6 specialized AI reviewers — free to start.