Imagine the scene: a customer finds the perfect product in your online store. Only one unit left. They add it to the cart, enter their details and, on clicking "Buy now", get a vague "Error" message. What happened? Maybe another customer was a millisecond faster. Or they tried to buy an invalid quantity. For the user, the frustration is the same. For your system, the difference is huge.
A robust, reliable shopping experience is not just about attractive design, but a technical architecture that handles the unexpected with surgical precision. At Marte Website Builder we believe excellence is in the details, and one of the most critical in e-commerce is stock management.
In this article we dive into the technical core of this problem: the correct use of HTTP status codes, specifically the battle between 409 Conflict and 422 Unprocessable Entity. We also share best practices on how your frontend and backend should communicate and why error internationalisation is a pillar of scalability. To illustrate these concepts, we draw on how robust platforms like Ecwid, our tool of choice, set the foundations for flawless handling.
The conflict scenario: Beyond "out of stock"
The most common problem is a race condition: two or more users try to buy the last available item at the same time. The system must choose a "winner" and elegantly tell the "loser" that inventory state changed while they were completing their purchase.
This is where choosing the right HTTP code becomes critical. It is not just a detail for programming purists; it is the first domino in how your application will react and what message the end user will see.
The right tool for each problem: HTTP 409 vs. 422
Although both are client errors (4xx family), they serve very different purposes.
HTTP 409 (Conflict): "You got to the party too late"
The 409 Conflict code is used when the user's request is perfectly valid but clashes with the current state of the resource on the server.
Analogy: You try to book seat 7A on a flight, but just as you confirm, someone else books it. Your request ("I want 7A") was valid, but the seat state ("available") changed to ("occupied"). There is a conflict. E-commerce use case: A customer tries to buy the last pair of shoes (quantity: 1). Their request is syntactically and semantically correct. However, at the exact moment of the transaction, that product's inventory went from 1 to 0. The request conflicts with the current state of the database.
A good API response should not be limited to the status code. It should include an explanatory JSON body with an error code (e.g. INSUFFICIENT_STOCK), message and details (productId, requestedQuantity, availableQuantity).
HTTP 422 (Unprocessable Entity): "What you are asking for makes no sense"
The 422 Unprocessable Entity code is used when the server understands the request and its syntax is correct, but it contains semantic errors or violates business rules that prevent processing. The resource state on the server has not changed; the problem is with the request itself.
Analogy: You order in a restaurant a "beef steak, negative cooking". The waiter understands every word, but the order is logically impossible to process. E-commerce use case: A user tries to add 0 or -1 units of a product to the cart; tries to buy 50 units of a product limited to a maximum of 5 per customer; sends a "colour" field with a value that does not exist for that product (e.g. "neon fuchsia" for a shoe only sold in "black" or "brown").
The API response here is ideal for pointing to exactly which field failed, with a code like VALIDATION_ERROR and details per field (field, issue, message).
Summary: Feature / HTTP 409 Conflict: Root cause = Conflict with current resource state. Was the request valid? = Yes, but the timing was wrong. Key example = Trying to buy an item that has just sold out. Solution for user = Retry later or accept the product is out of stock. Feature / HTTP 422 Unprocessable Entity: Root cause = Semantic errors in the request. Was the request valid? = No, it violated business rules. Key example = Trying to buy a quantity not allowed. Solution for user = Correct the request data and resend.
Best practices: Frontend and backend in perfect sync
The HTTP code is only the beginning. Error handling is a coordinated dance between server and client.
1. The backend is the single source of truth: The backend must be the guardian of state and business logic. It is responsible for sending the correct HTTP code (409 or 422) and, crucially, a structured JSON body. This JSON must contain an internal error code (e.g. INSUFFICIENT_STOCK) and a developer-readable message. 2. The frontend is the smart interpreter: The frontend should not show the user "Error 409". Its job is: to classify the error based on the HTTP status code (if (status === 409)); to determine the specific action based on the JSON internal code (switch (error.code)); to show a localised, user-friendly message.
Internationalisation (i18n): Speaking your customer's language
What if your store sells in Spain, Germany and France? You cannot let your API return messages in a single language.
The best practice is to decouple logic from messages.
Backend (language-agnostic): Send error keys, not text. Example: { "error": { "code": "INSUFFICIENT_STOCK" } }. Frontend (language-aware): Maintain translation files (e.g. es.json, de.json) and use the received key to show the correct message according to the user's browser language. Example in Spanish: "Oops! Someone got there first. This item has just sold out." In German: "Ups! Jemand war schneller. Dieser Artikel ist gerade ausverkauft."
This approach not only makes translation easier but allows you to change messages on the frontend without deploying backend changes.
Our experience with Ecwid
At Marte Website Builder we build powerful e-commerce on the foundations of Ecwid. One reason we trust this platform is that its API is designed following these best practices. Ecwid handles inventory conflicts internally and exposes clear responses that let us build custom user experiences.
Our value as engineers is not just "connecting Ecwid", but understanding its architecture so we can: intercept and handle these errors in a custom way in custom frontends (headless commerce); create integrations with third-party systems (such as an ERP) that react correctly to stock conflicts; translate technical API responses into clear, reassuring communication for the end buyer.
Conclusion
The difference between a 409 Conflict and a 422 Unprocessable Entity may seem a minor technical detail, but it reflects a development philosophy: the pursuit of precision and robustness. Well-implemented error handling turns a potential moment of frustration into a clear, honest interaction with the customer, strengthening trust in your brand.
A great e-commerce experience is built on thousands of correct technical decisions. This is undoubtedly one of the most important.
