Take a classic example: a one-time use coupon. Without some kind of locking, two simultaneous requests would be able to use the same coupon successfully. Roughly:
0.0s - [1] Client 1: Apply coupon
0.0s - [2] Client 2: Apply coupon
0.1s - [1] Server to database: Is coupon marked as used?
0.1s - [2] Server to database: Is coupon marked as used?
0.2s - [1] Database to server: Nope! All good.
0.2s - [2] Database to server: Nope! All good.*
* Since the question was asked for both requests at the same time, the answer was "Not used" in both cases. 0.3s - [1] Server to database: Update coupon as used.
0.3s - [2] Server to database: Update coupon as used.*
* Coupon has been used twice :(
Node's async model is not going to help you here. You will need something more, such as a mutex.Node give you freedom from Thread Hell. You enjoy similar performance without locks, threads, synchronisation. Race conditions happen but mostly with cache invalidation where you can have limited consistency guarantees.
If can model your database differently for this rudimentary example, then good for you – you're thinking about race conditions. Many web programmers do not think about them at all, and race conditions are usually not trivial to fix.
How is that specific to only NodeJs?
in fact, an entirely synchronous, 1-user-at-a-time server wouldn't fix this, if there were two or more servers. and honestly, who would design any system that only supports 1 concurrent user?