Known Limitations
These limits are part of the POC release posture, not hidden roadmap promises.
Deployment and Operations
- RiffDB is a pre-release proof of concept, and its dual license does not change its security, compatibility, or support limits.
- Linux is the supported deployment platform; protected credential and key-file loading is unavailable on other operating systems.
- The source convenience installer targets Linux systemd, requires a valid private
XDG_RUNTIME_DIRfor user-scope unit verification, and does not configure login sessions or lingering. - Automated source-install acceptance exercises user scope only, while system-scope installation requires first-install acceptance on a disposable or staging host.
- Application gRPC supports literal-loopback cleartext, verified direct TLS with static certificate and key paths, and a protected Unix socket, and hosted MCP supports literal-loopback cleartext or verified direct TLS, while the
riffdb-mcpstdio bridge’s upstream gRPC hop is loopback-only and OAuth, mTLS, automatic certificate issuance, and untrusted internet-facing operation are unsupported. - Browser code must use an application-owned backend and never receive a RiffDB credential.
riffdbdexposes only the documented POC configuration fields, with a loopback-only metrics listener and no storage-engine selector, general tuning surface, or secret values in TOML.- After generic bootstrap, systemd
activemeans the process started while authenticated Health remainsnot_readyuntil the first application contract is deployed. - The production server uses redb only, and the isolated Fjall comparison workspace is never linked into or shipped as a server binary.
- Benchmark reports are revision-specific evidence rather than a standing performance promise, with no absolute TPS gate and no valid claim without published hardware, filesystem, durability mode, workload, revision, and raw output.
- The sustainable TicketDesk rehearsal remains blocked by continuing-load source-receipt reclamation and final-window tail latency.
- Ordinary redb reads validate RiffDB envelopes, CRCs, schemas, and keys without verifying every engine page checksum, whereas offline physical verification requires extra disk space for a private copy and refuses repair or unrecovered journal suffixes; see startup integrity.
- The shared crash-recovery matrix covers the enumerated POC recovery boundaries rather than providing a general disaster-recovery guarantee.
- The POC authorization model uses opaque local capability tokens rather than a production identity provider or OAuth authorization server.
- Generic bootstrap deploys no application and grants its MCP developer no wildcard application-data authority until an administrator binds a compiled role or lineage-scoped capability.
- Convenience bootstrap capabilities expire after at most 30 days with no background daemon renewal, though operators can rotate capabilities explicitly with
riffdb capability rotate <CAPABILITY_UUIDV7> --credential-output <PATH> --revoke-oldorcargo riffdb bootstrap (--user|--system) --renew. - Re-running the source installer updates the three binaries while preserving existing keys, configuration, and unit files, and
cargo riffdb uninstallremoves only installed binaries and unit files without performing configuration migration, key rotation, data deletion, or format upgrades. - The source installer stages and backs up
riffdbd,riffdb, andriffdb-mcpinside.riffdb-binary-rollback-v1on the destination filesystem so an interrupted binary publication rolls back to the previous set on exit or at the start of the next install. - Optional Codex MCP registration serializes bootstrap callers through
$XDG_CONFIG_HOME/riffdb/.codex-mcp.lockand treats an identical existing server entry as idempotent, while external writers to the same user’s Codex MCP configuration outside that lockfile remain uncoordinated. - Metrics are exposed only over an optional literal-loopback HTTP listener (
GET /metricsandGET /v1/metrics) or periodic local NDJSON flight-recorder files (riffdb telemetry summarize <PATH>), with no non-loopback network metrics listener or push exporter. - Neither a clean restart nor a bounded dirty restart performs a full population scrub, and
riffdb storage scrubtakes the database offline for the entire pass with no partial scope, resume, or repair option. - Restart after an abrupt stop pays a storage-engine repair proportional to the database file size, and the first write after any restart rebuilds the in-memory command indexes once before admitting writes.
- Outbox delivery supports only the configured protected local archive directory (
[maintenance.outbox]/[databases.<alias>.outbox]andriffdb outbox archive), with no external network, webhook, or broker connector. - The optional systemd MCP socket shares one capability among members of its Unix socket group, so operators must spawn one bridge per client when principal identities must differ.
- Release verification validates systemd unit syntax and hardening directives without starting the units inside the host systemd manager.
- A POC-exit decision requires all POC-001 through POC-010 evidence together with a human architecture review.
Contracts and Writes
- There is no general SQL surface, arbitrary transaction callback, analytical join engine, distributed transaction, automatic failover, or consensus protocol.
- An ordinary command may atomically delete and return the transaction-current preimage of at most one complete-key, partition-local
no_inboundentity, whereas multi-row deletes must use the separately compiler-bounded collection deletion forms. - Reactive applications are partition-local and bounded, with no raw CDC, cross-partition ordering, wall-clock event retention, exactly-once external effects, event-sourced reconstruction, webhooks, or in-process agent inference.
- Protected event replay and reaction validation acquire the storage mutation fence to obtain a transaction-current capability, row, and relationship view, and protected workers use bounded consumer long-poll rather than the global reactive wakeup.
- Contract migration administration is available through the operator service, Rust client, and CLI, and is intentionally absent from MCP, TypeScript, Python, and generated application clients; Gate C rejects key swaps and predecessor-occupied rekey chains.
- The PostgreSQL counterexamples in the repository demonstrate only that unsafe write patterns remain expressible in a general SQL surface and are excluded from RiffDB’s compiled command surface.
Queries and Projections
- Runtime-selectable page sizes use the query-only
Limit<MAX>refinement up to 65,534 rows and do not refine offsets, byte budgets, contract integers, aggregate work, or projection candidate budgets. - A single RiffDB query invocation returns at most its compiled row limit (and never more than 65,534 rows or 4 MiB of encoded results), with no hidden multi-page response or streaming query protocol.
- Named bounded RiffQL aggregates and the ad-hoc projected CLI support exact counts (
count,count_present,count_distinct,count_distinct_present),sum,mean(overi64,u64, uniform-scaleDecimal, and uniform-currencyMoney),min,max, Booleanany/all, and bounded single- or multi-columngroup bywith canonical or explicit group-key--orderand top-N--limittruncation; compiled RiffQL queries additionally support boundedhavingandorder byover up to four aggregate or group-key items, while ad-hoc projected CLI queries do not expose ahavingclause or sorting by computed aggregate outputs. - Candidate algebra supports one compiler-sealed non-output binding across at most eight same-partition declared-index sources, one-level bounded one-to-many expansion, and at most 32 compiler-expanded root orders, without depth-two expansion, cross-partition joins, or caller-supplied sort expressions.
long_pattern_v1provides exact binary or Unicode-fold equality, literal affix/substring, and LIKE/ILIKE matching for values up to 8,000 bytes as a rebuildable candidate provider, without general regular expressions or direct unanchored negation.- Ordinary row-store indexes execute exact equality, one bounded membership or range/prefix branch, and the complete declared order, while canonical string ranges, multiple branching dimensions, residual post-page filters, and runtime join optimization remain compile-time refusals.
- The external tuple-capability fixture is a narrow source-compilation receipt for bytewise equality, membership, and order rather than a full external framework-conformance claim.
- Named vector search selects exact scan at or below the declared per-organization
ann_threshold(up to 500 rows when undeclared or 65,536 rows when declared) and first-party in-memory HNSW on primaries and followers above that threshold when a warm graph is available, refusing larger organizations withScanBudgetExceeded. - Vector staleness uses v1 count semantics (
stale_count > threshold) rather than duration-based thresholds. - Production
nearest()requires one explicit compiler-owned projected source withavailable, causal, or duration-bounded freshness and refuses multi-source vector queries, vector joins, or row-store fallbacks. - Columnar artifacts are demand-activated on their first semantic query, returning
Buildingwhile activation is running, retrying transient control-read unavailability on the next worker pass, and allocating a replacement candidate rebuild when a published artifact fails validation. - Projection state is derived and rebuildable, so projections may report degraded or building status while authoritative commits remain available.
- Tokenized-text search supports conjunction, capped disjunction, phrase, and bounded ordered proximity with fixed
riff_bm25_v1ranking across eight retained provider epochs, without wildcards, regular expressions, fuzzy matching, stemming, snippets, caller boosts, or hybrid vector/text queries.
Replication, Backup, and Restore
- Asynchronous follower replication, follower reads, operator registration and retirement, and explicit incarnation-fenced primary promotion operate on a single-primary topology without quorum durability, automatic failover, cascading followers, or multi-primary writes; see follower administration.
- Restore publication requires the database directory to be private to the sole configured service identity, and shared write access or concurrent server processes are unsupported.
- Full backup and restore publication are offline maintenance operations, while changelog-derived archive backup and restore operate at commit-sequence granularity (with storage-level wall-clock timestamp resolution via
resolve_archive_stop_at_timestamp) without built-in archive encryption; see backup and restore. - Destructive restore preserves
DatabaseIdwhile rewinding sequence allocators and bumping the durablehistory_incarnationfence (RDB-HISTORY-0101); statefulRiffDbClientandriffdb-mcpsessions automatically track and sendobserved_history_incarnationacross commit and event reads, while newly connected stateless callers that omit a priorobserved_history_incarnationadopt the restored incarnation. - Locators, cursors, sessions, read-after-sequence expectations, authorization observations, and idempotency assumptions from a destroyed history suffix are invalid after a restore.
Retention
Online retention (see Configuration) never
passes a fence, and in this POC two fences and one checkpoint interaction bind
more than an operator may expect (live state and active binding fence are
exposed on /metrics, /v1/metrics, and the periodic NDJSON flight recorder):
- When
[maintenance.outbox](or[databases.<alias>.outbox]) is omitted, no outbox worker is configured, so an emitted event is never marked delivered automatically and holds retention from the first undelivered event onward (online_retention_fence="undelivered_outbox") until local archive delivery is configured. - A declared columnar projection that has not been queried in the current process holds retention at its last populated frontier (
online_retention_fence="projection_durable_frontier", or at the beginning of history if never populated) until a query activates it or an operator detaches it withriffdb retention projection-detach. - Online retention invalidates the optional validated-prefix startup checkpoint when logical pruning commits and refreshes it off the commit gate once a retention batch drains, while a
Completedstartup registry binding preserves bounded restart even before that refresh finishes; see Startup integrity. - Online logical pruning is paced to about five percent of writer time in journaled steps of at most 256 sequences and can fall behind under sustained write saturation.
Storage reclamation
- Sealed journal extents (
<database>.riffjournal.sealed.<generation>) retain command and receipt history referenced by compact stubs in the database file and must never be deleted by hand. - A sealed journal extent is retired only after logical pruning and source-history reclamation release every command and receipt reference with no active reader or scrub holding it.
What a command cannot express
The compiler proves bounded structural properties of application writes; see the write cookbook. The command language has the following structural limits:
- Commands read entities by complete key or through one atomic indexed first-row selection whose equality prefix proves the partition and every conflict key before the read.
- An invariant may span entities inside one aggregate, and a command may mutate multiple aggregates that share a partition route, but no invariant may relate two distinct aggregates.
- A command cannot read a derived projection because write decisions must never depend on an asynchronous projection watermark.
- Allocating an unspecified free row from an unowned pool in a single round trip without root contention is not expressible inside one command.
- General multi-step durable workflows and sagas outside a single compiled command are not implemented in this POC.