Caching
Syntra ODBC uses an embedded local cache between your SQL clients and QuickBooks Desktop. This architecture delivers fast analytical query performance while keeping data fresh through incremental sync.
Architecture Overview
Section titled “Architecture Overview”Client (Excel, Power BI, etc.) │ ▼Syntra Server (port 5433) │ ├──▶ Local Cache (fast reads) │ ├──▶ Live reads (QuickBooks Enterprise) │ └──▶ Live QuickBooks fetch (for writes, and fallback reads) │ ▼ QuickBooks DesktopWhen a SELECT query arrives, Syntra chooses the optimal read path:
- Local cache: Default. Sub-millisecond reads from the local cache.
- Live reads: QuickBooks Enterprise feature. Low-latency reads directly from QuickBooks data. See Live Data Reads (Enterprise).
- Live QuickBooks fetch: Used when
QB_MAX_STALENESS = 0or the cache is stale. Requires QuickBooks Desktop to be running. Used for all write operations on every edition.
Incremental Sync
Section titled “Incremental Sync”Rather than re-fetching all data on every poll, Syntra uses incremental sync:
- On first startup, a full sync populates the local cache. On QuickBooks Enterprise with live reads enabled, tables served by live reads are read directly from QuickBooks and are not maintained in the cache (see Why some tables aren’t cached below).
- On subsequent polls, only records modified since the last sync timestamp are fetched.
- Modified records are upserted into the cache, and deleted records are removed.
This approach dramatically reduces the load on QuickBooks and keeps sync times short, typically under a second for small change sets.
Why some tables aren’t cached
Section titled “Why some tables aren’t cached”Incremental sync keeps the cache current by asking QuickBooks for records changed since the last poll, and it relies on QuickBooks’ deleted-record feeds to know which rows to remove. QuickBooks does not always report deletions through those feeds completely or promptly, so a purely incremental cache can briefly retain rows for transactions that have already been deleted or voided in QuickBooks.
For core financial tables, that is not an acceptable trade-off. So on QuickBooks Enterprise, when live reads are available, Syntra serves those tables directly from the QuickBooks data store instead of caching them. Every query reflects QuickBooks exactly as it stands at that moment, including deletions, with no staleness window and no dependence on the delete-tracking feeds. These tables do not need (and do not have) a cache entry, which is why CALL qb_sync_table() and CALL qb_rebuild_all() skip them.
Adaptive Polling Tiers
Section titled “Adaptive Polling Tiers”Tables are assigned to polling tiers based on how frequently they tend to change. Each tier has a different polling interval:
| Tier | Interval | Typical Tables |
|---|---|---|
| Hot | 60 seconds | Invoices, Sales Receipts, Payments, Bills |
| Warm | 180 seconds | Customers, Vendors, Items, Employees |
| Cold | 900 seconds | Accounts, Classes, Terms, Sales Tax Codes |
| Frozen | 3600 seconds | Company Info, Preferences, Templates |
How Tier Assignment Works
Section titled “How Tier Assignment Works”Syntra monitors change frequency for each table and can promote or demote tables between tiers:
- A table with frequent changes gets promoted to a faster tier.
- A table with no recent changes gets demoted to a slower tier.
- You can override tier assignments in
config.toml.
Configuring Tiers
Section titled “Configuring Tiers”In config.toml:
[cache.tiers]hot_interval = 60warm_interval = 180cold_interval = 900frozen_interval = 3600
[cache.overrides]# Force a table to a specific tiercustomers = "hot"company_info = "frozen"Cache Storage
Section titled “Cache Storage”The cache is stored as a single file on disk, typically at:
C:\ProgramData\SyntraODBC\cache.dbCache Size
Section titled “Cache Size”The cache file grows as more QuickBooks data is synced. Typical sizes:
- Small company (< 1,000 transactions): 5–20 MB
- Medium company (10,000–50,000 transactions): 50–200 MB
- Large company (100,000+ transactions): 200 MB – 1 GB
Cache Persistence
Section titled “Cache Persistence”The cache persists across Syntra restarts. On startup, Syntra validates the cache integrity and resumes incremental sync from where it left off.
Bypassing the Cache
Section titled “Bypassing the Cache”To force a live query that skips the cache:
SET QB_MAX_STALENESS = 0;SELECT * FROM customers;To rebuild the entire cache from scratch:
CALL qb_rebuild_all();See Special Commands for details.
Monitoring Cache Status
Section titled “Monitoring Cache Status”Check when each table was last synced:
SELECT table_name, last_sync, row_count, tierFROM qb_cache_statusORDER BY last_sync DESC;