Server Row Model
The query, cache, mutation, and streaming contract for database-backed BusinessCraft grids.
BusinessCraft grids often sit on top of large legacy tables. The server row model keeps those screens responsive by loading only the rows the user needs while preserving sort, filter, selection, edit, and export semantics.
When To Use It#
Use BcServerGrid when any of these are true:
- the table is too large to load into the browser,
- sort or filter must run in PostgreSQL or domain logic,
- rows are lazy tree nodes,
- export must walk the server result set,
- edits need pending, rollback, or server reconciliation states.
Client grids are still useful for small setup tables and local projections. For core ERP lists, start with the server row model unless there is a clear reason not to.
Modes#
The row model supports three fetch shapes:
pagedloads explicit pages and is the default fit for list screens.infiniteloads scroll blocks and prefetches in the scroll direction.treeloads children only when a parent expands.
<BcServerGrid
mode="paged"
columns={columns}
rowId={(row) => row.account}
loadPage={loadAccountsPage}
gridId="gl.accounts"
/>Query Shape#
The grid sends the current view state to the loader: sort, filters, search text, grouping, pagination, locale, and a view key. The server responds with rows, total counts when available, diagnostics, and cache metadata.
The loader should treat the query as the source of truth. Do not read sort or filter state from URL parameters separately once the grid has built a server query.
Cache Behavior#
The server row model owns:
- request dedupe for overlapping loads,
- aborting superseded requests,
- LRU block eviction,
- retry state,
- diagnostics for cache hit rate and queue depth,
- invalidation when the view key changes.
This keeps BusinessCraft screens from duplicating caching logic. The screen owns only the typed loader and mutation callbacks.
Edits And Streaming#
Server-backed editing should report pending and settled mutations through the server grid API. Streaming updates use ServerRowUpdate events so loaded blocks can update without dropping scroll, selection, or current filters.
useServerRowUpdates({
subscribe: (onUpdate) => subscribeToAccountUpdates(onUpdate),
gridApi,
});A loader should return rows for the requested view. Permission checks, domain validation, and persistence stay in server actions or domain packages; the grid should not know legacy business rules.
Related Demos#
The paged, infinite, tree, streaming, and CSV export demos show the same server contract from different angles. Use them together when designing a new ERP list screen.