Back to blog

Some integrations don't send you updates. They send you noise. Reconstructing the truth from it.

Webhooks have a simple promise. Something changes, you get called, you react. That promise makes integrations feel straightforward until you build one against a system that doesn't send you changes. It sends you fragments of changes. And fragments don't tell you what actually happened.

The gap between what you expect and what arrives

When you integrate with a system that fires a separate event for every property on an object, you are not receiving updates. You are receiving a stream of atomic notifications with no shared context, no guaranteed order, and no envelope telling you they belong together.

One contact record gets updated. Fifty properties change. Fifty webhook calls leave the source system. They arrive at your endpoint scattered across time, out of sequence, some duplicated, some delayed. None of them says this is part of the same update. None of them tells you when the update is complete. They just arrive, one property at a time, and wait for you to figure out what they mean together.

Now count that for multiple records updated within a second. Unrelatable.

At any meaningful scale, that stream becomes a firehose. The noise is not occasional. It is the default state of the integration.

What breaks when you process naively

The natural instinct is to process each call as it arrives. When a property changes, you write it. Another property change, you write it. The logic is simple, and it feels correct.

It is not correct.

What you are writing to your database is not the state of the object after the update. You are writing a sequence of partial states, each one reflecting a different moment in a change that hasn't finished arriving yet. If two calls arrive out of order, you write an older value over a newer one. If a call arrives twice, you process the same change twice. If your processing takes longer than the gap between calls, you are working on a state that is already outdated by the time you finish.

Your database looks like it's in sync. It is not. It reflects the noise, not the reality.

The decision that fixed it

The first instinct was to absorb the calls and reconstruct the state from the fragments. It didn't work. HubSpot wasn't sending them in order and wasn't sending them in any predictable time window. There was no reliable way to know when a batch of calls was complete because HubSpot didn't know either.

The fix didn't come from outside HubSpot. It came from inside it.

We built a workflow directly in HubSpot that listens for object saves and updates a single custom property we controlled. That property had one purpose: to be the signal. We ignored every other webhook entirely. When that custom property was updated, we knew the save was complete. We fetched the full object state directly from the API and updated our side once, cleanly, from a single source of truth.

The noise was still there. We just stopped listening to it.

What that produced

Zero data loss. No duplicate processing. No race conditions. A system that processes every object update exactly once, from a complete and accurate state, regardless of what HubSpot sends in between.

More importantly, the system became simple. One signal. One fetch. One write. The complexity of HubSpot's webhook behavior became invisible to everything downstream.

Why does this matter beyond one integration?

When an integration is fundamentally broken, the instinct is to build a smarter receiver. Absorb more, reconcile more, and handle every edge case from the outside.

That instinct is wrong.

The right question is whether the source system itself can be made to produce a better signal. In most platforms, you have more control than you think. A workflow, a custom property, a calculated field, something inside the system that you own and that collapses unpredictable behavior into one clean event you control.

The noise doesn't go away. You just stop listening to it. And sometimes that is the only solution that actually works.

Author image

Victoire Habamungu

Software engineer specialising in data systems, distributed architecture and platform engineering.

Share post: