What is wrong with this example NestJS service?
Practice this questionShort explanation:
The example performs a read, checks stock in application code, and later writes a modified value. Those steps are not one atomic operation, so another request can change the record between them. It also trusts the quantity without showing validation, making both business-rule and concurrency bugs possible.
Example and explanation:
async reserve(productId: number, quantity: number) {
const product = await this.products.findOneBy({ id: productId });
if (!product || product.stock < quantity) throw new Error('No stock');
product.stock -= quantity;
await this.products.save(product);
return product;
}-
Negative quantity can increase stock; zero/fractional values may also be invalid.
-
Two requests can read the same stock and overwrite each other's changes.
-
A generic error can become an unclear HTTP 500; map expected failures properly.
-
Check access and tenant scope if products belong to separate organizations.
-
With stock 5, two requests for 4 can both read 5 and both save 1, creating more reservations than available stock if subsequent logic accepts both.
Race timeline:
| Step | Request A | Request B |
|---|---|---|
| 1 | Reads stock = 5 | Reads stock = 5 |
| 2 | Checks quantity 4: allowed | Checks quantity 4: allowed |
| 3 | Saves stock = 1 | Saves stock = 1 |
| Result | Both may proceed with reservations | Stored stock hides the oversell |
- A transaction with an unprotected read/check/write pattern is not a universal fix; protect the update through an appropriate lock, version check or atomic condition.
Interview point:
- Show the interleaving and the invalid quantity case before suggesting an atomic update; explain why both fixes are required.