Back to blog
PrimentraPrimentra
·September 16, 2026·8 min read

Approve on Thursday, write Monday: what a stale approval request does to live data

Home/Blog/Approve on Thursday, write Monday: what a stale approval request does to live data
supplier SUP-1042 · payment termsMonsteward submits30 → 60request waits, holding 60Wedstaging feed writes60 → 45Thuapprover approves45 → 60Wednesday's correction is gone. Nothing on the screen said so.

A data steward opens supplier SUP-1042 on Monday, changes the payment terms from 30 days to 60, and submits it for review. The request goes into the queue. Both approvers are on holiday, so it sits.

On Wednesday night a feed from the purchasing system writes 45 days to the same supplier, because purchasing renegotiated. On Thursday an approver comes back, opens the queue, sees a tidy one-line diff reading 30 → 60, and clicks Approve all. The payment terms become 60.

Nobody did anything wrong. The diff was accurate on the day it was written. An approval request is a snapshot of the world as it was at submission time, and approving it replays that snapshot onto a world that has moved.

Approval replays, it does not merge

Worth being blunt about this, because every tool with a review queue has the same shape and most of them do not say it out loud. Approving a request applies the submitted values. It does not compare them against the current ones and it does not merge. The submitted value wins.

What keeps the damage small is narrower than it sounds: Primentra writes only the attributes present in the submission. If the steward edited payment terms and nothing else, approval writes payment terms and nothing else. A bank account somebody corrected on Tuesday survives, because it was never in the request. The blast radius is the columns the steward actually touched, not the row.

You lose a change in one case only: two people edited the same column, and one of them went through a queue.

The lock closes most of the doors

A record with a pending change is locked in the grid. You cannot edit its cells and you cannot tick it for a bulk operation. That one rule removes the obvious version of this problem, which is two stewards editing one supplier on the same afternoon.

The other doors were closed more recently. Since version 1.2026.8.23 a write through the REST API to an entity that requires approval is queued rather than written, and a file import into one is refused outright, naming the setting to switch off. We wrote up that audit in the post about every route into the product. Before it, an API integration could walk straight past a review gate the grid respected.

Two doors are still open, and both are deliberate rather than accidental.

The first is staging. A scheduled feed running at three in the morning has no user to notify and nobody who could meaningfully second-guess the source system, so staging applies its rows and moves on. That is the Wednesday night in the story above, and in practice it causes more stale requests than anything else.

The second is quieter. An API write is queued without checking whether a pending request already targets that record, so an integration can submit a second request for a row a steward already has in the queue. Approve one and the other goes stale the moment you do it.

What Primentra checks before it writes

Every changed record in a request stores the moment its live row was last modified, taken at submission time. When the request is opened, that moment is compared with the current one:

CASE
    WHEN row.EntityRowId IS NOT NULL
     AND row.RowModifiedAtSnapshot IS NOT NULL
     AND er.ModifiedAt > row.RowModifiedAtSnapshot
    THEN 1 ELSE 0
END AS IsConflict

A live row that has moved since submission marks that record as a conflict, and the API returns the flag alongside the request detail. Because the grid lock covers ordinary editing, a flag here almost always means the change arrived through one of the two routes above.

The limit, stated plainly: nothing in the requests screen renders that flag today. The database computes it, the API sends it, and no badge picks it up. Until one does, the check that works is the one a careful approver already makes. Look at the Modified column and the audit panel on the record before clicking, and use Send back rather than Approve when the diff no longer matches the live row.

What surprises people at the moment of approval

Deletions get no staleness check at all. An approved delete is applied as submitted, and whatever happened to the record while the request waited, the record and its values go. If another open request referred to that same record, its link is cleared, and that request now points at nothing.

A duplicate code behaves differently from what most people expect. A new record whose code already exists cannot be inserted, so Primentra marks that one record rejected and carries on with the rest. Nothing is overwritten and no duplicate appears. But the request then closes with some records applied and one refused, which is why the record statuses matter more than the headline on the request.

A failing rule is the opposite: it takes everything down with it. Rules run after the values are written, inside the same transaction. A warning is recorded and the approval carries on. An error rolls the whole approval back, and the panel names the rule and the attribute. So an old request can fail today on a rule that did not exist on Monday.

Queue age is the number to watch

All of these failures scale with how long a request waits. A request approved within the hour cannot go stale in any interesting way. A request that waits nine days on an entity fed nightly has had nine chances.

Count the days on your oldest pending request, then. The number of requests in the queue tells you much less. This query gives you the twenty oldest:

SELECT TOP 20
       ar.Id,
       e.Name AS EntityName,
       ar.SubmittedAt,
       DATEDIFF(day, ar.SubmittedAt, GETUTCDATE()) AS DaysWaiting
FROM   ApprovalRequests ar
JOIN   Entities e ON e.Id = ar.EntityId
WHERE  ar.Status = 'pending'
ORDER BY ar.SubmittedAt ASC;

Three practical rules follow from it. Keep the queue short, and treat a request older than a few days as something to chase rather than something to approve. Point bulk loads at entities that do not also carry an approval queue, or accept that the feed wins. And when a diff no longer matches what you see on the record, send it back instead of approving it, so the steward resubmits against today's values.

Ask this of whatever you are evaluating

Every MDM tool with a review step carries a version of this, so it is a fair thing to put to a vendor in a demo: what happens when the record changes while the request waits? Be careful with a tool that merges for you, because something picked the winning value and did not write down why. The answer you want is boring. It overwrites, it only touches the columns that were submitted, and it can tell you the row moved underneath.

That is where we are, with the badge still to build. Approvals are covered end to end in the walkthrough from edit to live data, and the reference page is Conflict Detection.

Common questions

What happens to the change somebody made while the request was waiting?

If the request touched that same column, it is overwritten without a word. If the request did not touch it, it survives. Approval writes only the attributes present in the submission, so the blast radius is the columns the steward actually edited, not the whole row.

How does Primentra know a request has gone stale?

Each record in a request stores the moment its live row was last modified at submission time. Opening the request compares that moment with the live row now. A newer live row marks that record as a conflict and the API returns the flag with the request detail.

Does the approval screen show me the conflict?

Not yet. The flag is computed in the database and returned by the API, and no badge renders it in the requests screen today. Until it does, the reliable check is the Modified column on the record and the audit panel next to it.

Can I still approve part of a request?

Yes, and sometimes Primentra does it for you. A new record whose code already exists is marked rejected on its own and the rest of the request continues. A request can close with some records applied and one refused, so read the record statuses afterwards rather than the request headline.

What if a business rule fails during approval?

Rules run after the values are written, inside the same transaction. A warning is recorded and the approval continues. An error rolls the whole approval back, nothing is applied, and the panel names the rule and the attribute that failed.

Run the Monday-to-Thursday test yourself

Submit a change, alter the same record through staging, then approve it. The 60-day trial installs on your own SQL Server, so you can watch which value wins rather than take our word for it.

Start free trial →Read the conflict docs →

More from the blog

Your approval workflow only works if every door respects it7 min readAudit trail retention: the audit log that deleted the answer on day 918 min readStaging Table Drift: How Primentra Catches a Column That Stopped Arriving9 min read

Ready to migrate from Microsoft MDS?

Download Primentra and run it on your own server, or try the live demo first. All features included.

Download Free TrialTry DemoCompare MDM tools
Approval Conflicts: When Old Values Win | Primentra