7

I'm designing an e-commerce application. Main flow is pretty straightforward: customer add items to basket, checkouts the basket (place an order) and waits for delivery.

There are following requirements:

  • basket is kept on backend
  • system should handle +5M baskets/orders per day

I know there is no single answer, but I'm looking for some comments/inspirations on how to design the basket & order module(s). I see following options:

  1. basket and order are separate services, and basket sends to order an ID of a basket to checkout, then orders calls basket for a basket details

1A) API call based communication

1B) async message based communication

  1. basket and order are separate services, and basket sends to order a full basket details

2A) API call based communication

2B) async message based communication

  1. basket and order are the same service, and checked-out basket becomes an order (it is same entity, just presented to user as basket or order, depending on it's state)
1
  • I'm for 1B. It makes services adequately decoupled.
    – Euphoric
    Commented Jan 17, 2021 at 8:13

1 Answer 1

6

All three make sense. However:

  • The third one may be a valid option for a small application, but if the system grows, you'll tend to separate those services, given that their logic is completely separate: you don't need to know how to add products to a basket in order to order, and you don't need to know how to check for credit card number in order to manipulate the basket. So maybe not a good idea to use the third approach in your case.

  • (The first option creates a circular dependency between the services. This may not be a technical problem by itself, especially with a message bus (but even with API calls, it doesn't either), but it may be strange to reason about in some situations.)

  • The choice between API calls vs. a message bus depends a lot on your skills (and the skills of your team). API calls tend to be simpler to reason about, especially in problematic situations. Imagine that the basket service sends a message that the order service should process. A network issue delays the message. After some time, the basket service sends the message again. Immediately after that, the network is up to normal, and both messages are delivered to the order service. What happens? Or here's another situation. The original message is delivered and processed, but the acknowledgement never arrives.

    If you had prior experience with a message bus (especially the edge cases where something goes wrong, MQS nodes fail, etc.), then go for it. If not, plain API calls may be a better alternative: you'll have the exact same problems with API calls too, but they usually tend to be simpler to reason about.

3
  • thanks for great input. I'll wait for other answers before marking answer as "Accepted". Commented Jan 18, 2021 at 10:25
  • What is the best practice of addressing the "duplicate message delivered due to network issue" ?
    – MLEE
    Commented Jan 19, 2021 at 6:40
  • 1
    @MLEE: there is no one single best practice for that, but several different approaches. The fact that two instances of the service may process the two messages in parallel makes things only more difficult (you can't, say, tag the messages on the sender side, and discard the duplicates on the receiver side later). Message queue services usually have two modes: they can guarantee a delivery (i.e. you will receive the message at least once), or they can guarantee that there would be no duplicates (i.e. you may receive a message), but not both at the same time. Commented Jan 19, 2021 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.