They Changed It and You Didn't Deploy
One of the more disorienting incidents in software is the one where nothing changed on your side. No deploy, no config edit, no migration — and yet the integration that worked on Monday is returning something different on Tuesday. A field that used to be present is now omitted when it’s empty. An identifier that was always numeric now sometimes has a prefix. A response that took 200 milliseconds now takes four seconds under some conditions the vendor hasn’t described. Your version history is a perfect record of everything you did, and none of it explains what happened.
This is a structural property of depending on someone else’s running system rather than a library you pinned. A pinned dependency changes when you decide it changes. A hosted API changes when its owner deploys, which is to say continuously and without notice, and the compatibility guarantees are usually narrower than they appear. A vendor can honor “we won’t remove fields from v1” while still changing which values a field can hold, how fast responses come back, and what happens at the edges — and the edges are where your code makes assumptions it never wrote down.
The practical defense is defensive parsing on the way in. Code that treats an external response as trusted structure — indexing into arrays, assuming a field exists, casting a string to a number — will fail in whatever way the language fails, at some distance from the actual problem. Code that validates the response against what it actually needs fails immediately, at the boundary, with a message naming the field and the value. That difference matters most on the day something changes upstream, because it converts a confusing downstream error into an obvious statement about the external input. It also gives you somewhere to notice: an alert on validation failures at an integration boundary is a change-detector for a system you can’t otherwise watch.
The sandbox deserves specific suspicion here. Test environments provided by vendors tend to be simplified — fewer edge cases, cleaner data, more forgiving latency, sometimes a different version entirely — which means passing tests against a sandbox proves less than it appears to. The gaps show up as the classes of failure that only exist in production: rate limits that only bite at real volume, records with fifteen years of history rather than three sample rows, and behavior under partial failure that the sandbox never simulates because it never has outages. That’s not a reason to skip sandbox testing; it’s a reason not to mistake it for evidence that the integration works.
The stance that follows is treating an external dependency as an input to validate rather than a component to trust, and to keep watching after launch rather than only during integration. The vendor’s change log, when they have one, is worth reading. Their status page is worth an alert. But the durable version of this is your own code noticing when the shape of what it receives stops matching what it expects — because the changes that hurt are exactly the ones nobody thought to announce.