FluxDB Rebuilds the Database Client in Rust + GPUI: Bounded Queries, Virtualized Tables, and Slot-Aware SQL Completion
Native Rust tooling now has a concrete reference for building database clients that stay responsive at scale without Electron's memory cost. The same patterns, from LIMIT n+1 to latest-wins completion, apply to any SQL editor or data grid that must handle large result sets gracefully.
FluxDB is a native cross-platform database client written in Rust and GPUI, with no Electron or WebView layer. It stays responsive because queries, rendering, completion, and writes have explicit boundaries. Queries get a default 100-row limit and a 16 MiB result memory budget; PostgreSQL pages fetch one extra row to detect has_more without COUNT(*); and the grid virtualizes both rows and columns so only visible cells become UI elements. Cell previews are clipped to 300 characters at character boundaries while full values remain available for editing, copying, and detail views.
SQL completion is the second major piece. Instead of matching text before the cursor against keywords, the fluxdb-completion crate parses the incomplete statement and locates a syntax slot. A tolerant parser masks the partial word with equal-length placeholders, lexical scopes handle aliases that shadow each other, and foreign-key metadata drives JOIN ... ON suggestions. A LineColIndex maps parser character positions to byte offsets so Chinese and emoji don't corrupt offsets. The pipeline is bounded: 64 KiB window around the cursor, 200 candidates, 75 ms debounce, and a latest-wins adoption guard that drops stale results.
Editing is staged locally in a DataChangeSet, then committed inside one transaction in delete, update, insert order. Updates and deletes must affect exactly one row or the batch rolls back. Performance budgets are explicit in code: background work like completion targets 100 ms, frame-sensitive work targets 16 ms, and large documents degrade syntax highlighting to lexical analysis. The result is a working template for keeping a native database client fast without hiding data loss behind silent truncation.
Bounding every layer is what makes the client feel fast; once query size, rendered rows, candidate count, and analysis window have explicit caps, performance becomes diagnosable rather than mysterious.
The three-state WriteValue distinction is a small modeling decision with large consequences: treating NULL as omitted is a common source of data corruption in database tools, and preserving intent until commit avoids it.
Completion design that assumes SQL is always incomplete while typing, and parses anyway by masking the cursor word, is more robust than falling back to prefix matching on parse failure.
Because GPUI Tasks can't kill a running future, the UI relies on adoption guards; async cancellation in native UI frameworks often needs explicit result validation, not just dropping a task.
The 500-table cutoff and 64 KiB window trade metadata completeness for startup and keystroke latency; large databases pay for columns only when a table is actually referenced.
How does pagination continue for an extra-large single row?
Currently there is a 16 MiB limit; if exceeded, it prompts truncation. Large fields will be specifically optimized later.