FUNDAMENTALS
Sync-and-store vs pass-through: choosing per object
Storing data makes reads fast; passing through keeps it out of your systems. Why the right answer differs for invoices, ledgers and catalogs.
By Unify Int team4 min read
- architecture
- data-handling
- unified-api
Every integration layer makes one architectural choice early: does it keep a copy of the data, or fetch it from the source on every request?
Vendors often pick one model and argue it is the right one. In practice, the answer depends on the object. Invoices, general ledger detail and product catalogs have different freshness needs, different sensitivity and different access patterns. This post explains both models and how to choose per object.
The two models
Sync-and-store
The integration layer syncs records from the source platform on a schedule or on change, and keeps an encrypted copy. Your reads hit that copy.
- Fast reads. Responses come from a store you control, not from a rate-limited vendor API.
- Consistent pagination and filtering, even when the source API is limited.
- Change events. Because the layer sees every change, it can emit webhooks, even for platforms that don't offer them.
- Resilience. Reads keep working when the source platform is slow or down.
The cost: a third party holds a copy of your customers' data, the copy can be stale between syncs, and initial sync takes time for large accounts.
Pass-through
The integration layer translates each request into a live call to the source platform and returns the result. Nothing is stored beyond logs and metadata.
- No stored copy. Easier security reviews and data residency answers.
- Always current. You see what the source has right now.
- No initial sync. Useful immediately after a customer connects.
The cost: every read is subject to the source's rate limits and latency, filtering is limited to what the source supports, and change detection needs polling or the platform's own webhooks.
Comparing them
| Sync-and-store | Pass-through | |
|---|---|---|
| Read latency | Low, predictable | Depends on the source |
| Freshness | As of last sync or event | Live |
| Rate limit exposure | Mostly during sync | Every request |
| Filtering and search | Rich | Limited to the source |
| Webhooks on change | Yes, generated | Only if the source emits them |
| Data held by provider | Encrypted copy | Logs and metadata only |
| Works when source is down | Yes, stale | No |
Neither column is better. They suit different objects.
Choosing per object
The useful question is not "which model does our vendor use?" but "which model fits this object, for this product?" Some typical answers:
Catalog and orders: usually store
Product catalogs and order histories are large, read often, and filtered in many ways. Commerce tools need change events when a price or stock level moves. Storefront APIs have rate limits that make repeated full reads expensive.
Storing them makes product features fast and lets the layer generate webhooks for platforms that don't send them.
Invoices and bills: usually store, sometimes pass through
AR and AP products read invoices and bills constantly, filter by status and date, and react to payments. Storing them supports fast lists and reliable "invoice paid" events.
Some teams pass them through anyway, because their security review treats any copy of customer finance data as out of scope. That is a valid choice if your read volume fits the source's limits.
Ledger detail and financial statements: often pass through
General ledger lines, trial balances and full financial statements are sensitive and read less often. A lender may pull them at underwriting and monthly after. Fetching them live keeps the most sensitive data out of storage and guarantees current numbers.
Reference data: store
Chart of accounts, tax rates, currencies, departments and locations change rarely and are needed for every write's validation. Store them and refresh on a schedule.
Bank and payment detail: depends on your product
Payout breakdowns support reconciliation and benefit from storage. Raw account and card details may fall under stricter rules. Check your obligations before choosing.
A worked example
A lending product might configure:
| Object | Model | Why |
|---|---|---|
| Invoices, bills | Sync-and-store, hourly | AR aging, payment events |
| Orders, payouts | Sync-and-store, every 15 minutes | Sales velocity |
| Chart of accounts | Sync-and-store, daily | Reference for mapping |
| Trial balance, P&L | Pass-through | Sensitive, read at review points |
| Journal entry lines | Pass-through | Sensitive, large, rarely listed |
The same product reads all of it through one API. The model is a per-object setting, not a different integration.
What changes in your code
If the integration layer handles both models behind one API, very little changes in your code. A few points to keep in mind:
- Freshness fields. Stored objects should tell you when they were last synced. Show that in your product where it matters.
- Latency budgets. Pass-through reads take as long as the source. Don't put them in a hot path that needs a fast response.
- Webhooks. Generated change events exist only for stored objects. For pass-through objects, poll or rely on platform events.
- Errors. Pass-through reads surface source outages directly. Handle them gracefully.
Questions for your security review
Reviewers will ask:
- Which objects are stored, and where?
- How are they encrypted, and who can access them?
- How long are they kept, and how are they deleted?
- Which objects are never stored?
Having a per-object answer, rather than "the vendor stores everything" or "nothing is stored, so reads are slow", makes the review shorter and your product better.
How Unify Int fits
Unify Int lets you choose sync-and-store or pass-through per object. Stored objects are encrypted, refresh on schedules you set, and power signed webhooks through Unify Sync. Pass-through objects are fetched live and never stored beyond logs.
See Unify Sync, Security and the Trust center.