I'm currently building my first ever microservice using NodeJS, but I stumbled upon a problem.
TL;DR ~ How to ensure data consistency between 2 microservices while both having write permissions
Setup
I currently have 2 independent microservices: session & recovery
- Session: Handles authentication (sign up, sign in, sign out, current user)
- Recovery: Handles password resets (request a reset, reset the password)
Both services contain an identical copy of the user table. Every record has a version
field to ensure data consistency.
I'm using a message broker (NATS) in between the 2 services.
Example
A brief example of how the application flow works.
Let's say we want to do a password reset: Recovery Service:
- Request password reset
- Generate token
- Specify new password (legitimized by token)
- Increase the version of the user
- Send
UserUpdatedEvent
Session service
- Receives event with data (user id, user version, new password)
- Search for a user with specified
id
andversion - 1
- Found? Update the password
- Increase version number
Important:
- The recovery service doesn't hold all the user data. In fact, it's only used to check if the user exists.
- The password is not stored inside the recovery service, it's send to the session service via the
UserUpdatedEvent
.
These are the 2 tables inside the recovery service:
- Recovery table: Contains the user reference , a generated token, the status (pending, expired, completed)
- User table: Contains the user id and the user its version
This works fine, but what if you update the same user simultaneously in both services?
The Problem
What if 2 microservices, that hold a copy of the same table, both modify different a property at the same time?
Example:
- Recovery service handles password modification for a user
- Session service handles all other modifications for a user (first name, last name,...)
They will both, at the same time, modify their tables. Therefor increase the version count and then emit an event to the other services. When the UserUpdateEvent
is received by the other services it won't be recognized as a 'legit' event since there is a version mismatch between session
& recovery
.
- Does this mean I should have kept this functionality in one service?
- Perhaps only one service should be able to modify a table?
- Maybe I shouldn't keep a version inside the recovery table at all?
Hopefully a more experienced person can help me out!