Home Blog SQLite mirror

Why we built a local SQLite mirror

FTS5, vector search, and a deliberate choice to keep agents off the OData hot path.

February 18, 2026 · 11 min read

Every SAP API call is a round-trip to a production system. Every round-trip is a load on the tenant, a token refresh, and a line in someone's rate-limit budget. When an agent wants to search master data, it should not hammer OData. It should query a local mirror.

The problem

An agent that needs to look up a business partner, a GL account, or a supplier has two bad options: call the live API every time (slow, rate-limited, load on prod), or keep a copy in memory (lost on restart, no search). Neither scales.

The design

sapctl mirrors fetched OData rows into a local SQLite database with FTS5 full-text search. The mirror tracks a watermark per entity, so incremental sync pulls only what changed since the last cursor.

sapctl s4 odata get --cred sandbox --service API_BUSINESS_PARTNER \
  --entity A_BusinessPartner --mirror

sapctl mirror search --query "acme" --entity A_BusinessPartner
sapctl mirror stats

Extract once, consume downstream. Agents read from the mirror; the live API is only touched on sync.

Why FTS5

SQLite's FTS5 gives us full-text search with zero extra infrastructure. No Elasticsearch cluster, no vector database to operate. For the 95% of SAP lookups that are keyword searches, FTS5 is fast, local, and free.

Why this matters for agents

An agent that reads from a local mirror is faster, cheaper, and kinder to the production tenant. It also stays on-policy: the mirror is populated by sapctl's constrained, audited calls, not by an agent's ad-hoc queries.

What this buys you

Extract once, consume downstream. A local SQLite mirror is the difference between an agent that respects the production system and one that hammers it.

Back to blog