Handle Stale API Responses

Hello guys I have an n8n workflow that updates customer data through an external API and then stores the API response in PostgreSQL.
The problem is that the API can return an older version of the customer record because another update may have happened between the request and the response.
For example:
n8n → Update Customer → API
↓
API Response
↓
PostgreSQL
I don’t want an older API response to overwrite newer data already stored in PostgreSQL.
Would you compare timestamps or version numbers from the API before updating the database?
Something like:
UPDATE customers
SET api_data = $1,
updated_at = $2
WHERE customer_id = $3
AND updated_at <= $2;
How would you handle APIs that don’t provide a reliable version number or timestamp?

Describe the problem/error/question

What is the error message (if any)?

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)

Share the output returned by the last node

Information on your n8n setup

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:

@Peter_Gavin Your SQL idea works!

If the api gives no realiable version, stamp the request, before calling the api, bump a counter in postgres, and pass that number through and only write if its the higest one. Don’t trust the update response at all, do a fresh get, and make sure only 1 customer runs at a time like a update

Hi @Peter_Gavin welcome

I would avoid trusting the API response blindly. The main thing is to make sure an older response can’t overwrite newer data in PostgreSQL.

If the API provides a reliable version or timestamp, use it as a guard:





UPDATE customers
SET api_data = $1,
updated_at = $2
WHERE customer_id = $3
AND updated_at <= $2
RETURNING customer_id;

If RETURNING gives no row, the database already has newer data, so n8n can safely ignore that response.

If the API doesn’t provide a reliable version, I’d create my own version when sending updates

:Read Current Version
        ↓
Send Update + Version
        ↓
Receive Response
        ↓
Compare Version
        ↓
Update PostgreSQL Only If Current


For APIs that don’t support versioning at all, I’d keep the API response separate from the authoritative customer record rather than blindly replacing the whole row.

Hi @Peter_Gavin, use the API’s record version if it provides one, and keep the comparison inside the UPDATE, not in a separate IF node before writing.

For your timestamp query, updated_at < $2 prevents equal timestamps from overwriting each other too. But the timestamp must come from the source record, not when n8n received it. If two different updates share a timestamp, it still cannot tell you which is newer.

The local counter suggested above only orders your own requests. Request 12 could still return older customer data than request 11, and another GET can also be stale if the API reads from a lagging replica.

Without reliable source ordering, I’d store those responses separately rather than automatically replace the customer row. Which API is this? Its read-consistency guarantees determine whether fetching again can actually resolve this.

The guidance provided by @Niffzy and @Anshul_Namdev on the n8n community forum is accurate and aligns with optimal database handling practices for concurrent data processing. Utilizing an atomic UPDATE statement with a timestamp check directly inside a PostgreSQL node prevents race conditions that could otherwise occur if separate conditional nodes were used prior to the database write. For further technical details, visit n8n Community.

Thanks for the solid explanation @Anshul_Namdev and @Niffzy!

Handling the version check directly inside the atomic SQL UPDATE statement instead of a separate IF node makes total sense to avoid race conditions.

Moving the source timestamp validation right into Postgres is definitely the cleanest way to prevent stale overwrites. Really helpful thread!

When the API does not give a reliable timestamp/version

You have a few practical options:

1. Best simple approach
Store the time you sent the update request and only accept the response if it arrives within a short window (e.g. 10–30 seconds). After that, treat it as potentially stale and skip the write.

2. Use your own version
Keep a local_version (or etag) column in PostgreSQL.
Increment it every time you successfully update the customer.
When the API response comes back, only write it if your local version hasn’t changed since you made the request.

3. Last-write-wins with caution
Always write the API response, but also store api_received_at.
Later you can detect and clean up obvious overwrites if needed.

4. Merge instead of overwrite (when possible)
Only update the fields that the API actually returned, and leave the rest of the row untouched.

Recommended pattern most people use

UPDATE customers
SET
api_data = $1,
updated_at = GREATEST(updated_at, $2), – keep the newest timestamp
last_api_sync = NOW()
WHERE customer_id = $3
AND (updated_at IS NULL OR updated_at <= $2);