The most expensive bug I have shipped did not throw an error. It returned a 200. The user saw a green checkmark that said their change was saved. The system of record never got it. Everyone downstream believed something that was not true, and because nothing failed loudly, nobody noticed until the numbers stopped reconciling weeks later, on a contractor's books, where wrong numbers are not an abstraction.
I have built this portal's entire integration around the lesson from that day: a success response from the backend is a claim, not a fact. The API telling me it sent the write is not the same as the write existing.
The architecture splits along a hard line. Reads come straight from SQL views over the live database, with no cache in between. Writes go through the ERP vendor's REST write API. The reads skip the API's own cache on purpose, because that cache can trail the live database by up to an hour, and an hour-stale number sitting in front of someone approving a financial review is not a small inconvenience, it is a wrong decision waiting to happen. So reads go to the source. Writes have to go through the API, because that is the only sanctioned way to mutate the system of record. You read from the truth and you write through the front door, and those are not the same path.
The front door is where the discipline lives. Every write is wrapped. The wrapper does the write through the API, and then, after the API reports success, it runs a verify callback that queries the real base table and confirms the row is actually there, with the values it should have. The point is blunt: a "sent" status is misleading observability. If the only thing your system records is that it called the API and got an acknowledgment, your observability lies to you in exactly the moments you most need it to be honest. The acknowledgment can be optimistic. The operation can be asynchronous and still in flight. A trigger on the far side can reshape or reject the row without a word. The only evidence that a write landed is reading it back, so that is what the wrapper does, on every write, every time.
There is more than one way into the ERP, so there is more than one wrapper. API writes go through the tracked path with its verify callback. Direct stored-procedure and SQL writes go through a separate write-guard wrapper carrying the same intent. The shapes differ. The contract does not. If you wrote to the system of record, you confirmed it landed.
Asynchronous operations are where a naive integration declares victory early. The API accepts the request and processes it later, returns its cheerful acknowledgment, and a lazy caller moves on. This portal polls server-side for the operation to actually complete and verifies the result once it has. The success the user sees is tied to the confirmed outcome, not the accepted request. It is slower to report success. It is honest about what success means, which on a system of record is the only kind of success worth reporting.
And because a discipline that depends on every author remembering it will eventually meet an author who forgets, including a future me or an agent generating a plausible handler, the verify-after-write rule is enforced by a lint check in CI. A new write path that does not route through a verifying wrapper fails the build. That gate exists because of the 200 that lied, and because of a later audit that found a hand-rolled write that had gone around the wrappers entirely, invisible to everything the rest of the system relied on.
The bug that hurts on a system of record is not the one that errors. It is the one that succeeds on paper and not in fact, because it corrupts the thing everyone else trusts, silently, with a green checkmark on top. Now that bug cannot stay silent here: an unverified write fails its check, and a write that lies about landing gets caught when the verifier reads back nothing. A 200 is the start of the question, not the answer.
Keeping a business's data correct while an AI agent moves fast against it is most of the real work in putting AI to work in operations, and it is what I build for clients as an embedded engineer. If your integration treats the backend's word as proof, that is worth pressure-testing, and a good conversation to start at /contact.