0
0
Rest-apiDebug / FixIntermediate · 4 min read

How to Handle Concurrent Updates in API Calls Safely

To handle concurrent updates in an API, use optimistic locking by including a version or timestamp in your data and checking it before saving changes. This ensures updates do not overwrite each other silently and helps maintain data integrity.
🔍

Why This Happens

Concurrent updates happen when multiple clients try to change the same data at the same time without coordination. This causes one update to overwrite another, leading to lost or inconsistent data.

python
data_store = {'item': {'value': 100, 'version': 1}}

# Client A reads data
client_a_data = data_store['item'].copy()

# Client B reads data
client_b_data = data_store['item'].copy()

# Client A updates value
client_a_data['value'] = 200
# Client A saves data

data_store['item'] = client_a_data

# Client B updates value
client_b_data['value'] = 300
# Client B saves data, overwriting Client A's update

data_store['item'] = client_b_data

print(data_store['item'])
Output
{'value': 300, 'version': 1}
🔧

The Fix

Use optimistic locking by checking the version before saving. If the version changed since reading, reject the update and ask the client to retry. This prevents overwriting newer changes.

python
data_store = {'item': {'value': 100, 'version': 1}}

def update_item(new_value, client_version):
    current = data_store['item']
    if client_version != current['version']:
        return 'Error: Data has changed, please retry.'
    # Update value and increment version
    data_store['item'] = {'value': new_value, 'version': current['version'] + 1}
    return 'Update successful'

# Client A reads
client_a_version = data_store['item']['version']
# Client B reads
client_b_version = data_store['item']['version']

# Client A updates
print(update_item(200, client_a_version))
# Client B tries to update with old version
print(update_item(300, client_b_version))

print(data_store['item'])
Output
Update successful Error: Data has changed, please retry. {'value': 200, 'version': 2}
🛡️

Prevention

To avoid concurrent update issues, always implement version checks or timestamps in your API data models. Use atomic database operations or transactions where possible. Communicate update conflicts clearly to clients so they can retry safely.

Best practices include:

  • Use optimistic locking with version numbers or timestamps.
  • Apply atomic updates in your database.
  • Return clear error messages on conflicts.
  • Consider pessimistic locking only if necessary, as it can reduce performance.
⚠️

Related Errors

Similar issues include:

  • Lost updates: When one update silently overwrites another.
  • Dirty reads: Reading uncommitted changes from another transaction.
  • Deadlocks: When two processes wait on each other’s locks.

Quick fixes involve using proper transaction isolation levels and locking strategies.

Key Takeaways

Always use version or timestamp checks to detect concurrent updates.
Reject conflicting updates and ask clients to retry with fresh data.
Use atomic database operations to keep data consistent.
Clear error messages help clients handle conflicts gracefully.
Avoid pessimistic locking unless absolutely needed due to performance costs.