=============================================================================== URL: https://reifydb.com/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started One database instead of Postgres + Redis + a queue + a cron job. Your writes, your rules, and your derived views run in one transaction, inside the database, as the user who asked. No caches to invalidate. No cron to babysit. No drift to debug. Read the Docs View on GitHub Built-in Testing ctrl+enter to run Explore all examples → Take the tour → Open playground → The Stack You have built this. You have a database. Then the product needed to be fast, so the hot rows got copied into Redis. Then a dashboard needed a total, so a cron job started recomputing it. Then a rule had to run when an order changed, so it moved into a worker behind a queue. And all of it connects to the database as one account, with one password. You did not architect that. You accumulated it. Today +---------------+ | POSTGRES | +---------------+ ~ glue ~ +---------------+ | REDIS | +---------------+ ~ glue ~ +---------------+ | CRON | +---------------+ ~ glue ~ +---------------+ | QUEUE | +---------------+ ~ glue ~ +---------------+ | WORKERS | +---------------+ five systems, one state | v With ReifyDB +---------------+ | REIFYDB | | | | tables | | views | | transitions | | primitives | +---------------+ one system, one transaction Replaces Every box is an apology. Each system in that stack exists because the database could not do one specific thing. Here is what each one is standing in for, and what takes its place. [ REDIS ] The hot copy. The database could not serve these rows fast enough, so now there are two of them. One is right. REDIS → tables, already in memory [ CRON ] The refresh. The database could not keep a derived number current, so it is recomputed on a timer. Between runs it is wrong, and it looks fresh. CRON → views, current on write [ QUEUE + WORKERS ] The rule, later. The database could not run your logic when the data changed, so the logic runs afterwards, elsewhere, and hopes the data has not moved. QUEUE + WORKERS → transitions, inside the transaction [ SERVICE ACCOUNT ] The one password. The database could not tell your users apart, so everything connects as one privileged account and the code in front of it decides who may do what. Every rule lives twice, one connection can do anything, and queries get built from user input on the way through. SERVICE ACCOUNT → per-user auth and policies [ GLUE ] The code that knows. None of the above knows about the others, so you wrote the code that does. It is the most fragile code you own, and it ships no feature. GLUE → nothing What ReifyDB Is Same feature. Two stacks. ReifyDB is one database for that state. Tables hold the rows. Views hold the derived numbers, and the write keeps them current. Rules run inside the transaction, as procedures and handlers you version and test. Counters, queues, ring buffers, and histograms are built in. And it knows who is asking: clients authenticate as themselves, and policies decide, per user, what may be read and written. Alice places an order. First on today's stack, then on ReifyDB. Today alice POST /orders api server may alice? build the query as "app", the one account postgres insert, debit redis drop cached balance queue worker: totals cron revenue, later alice polls balance, revenue: stale in between 5 systems runs as "app" stale With ReifyDB alice place_order(...) reifydb policy alice may place orders procedure check balance, insert, debit view revenue, updated by the same write one transaction alice sees balance, revenue: current, pushed 1 system runs as alice current Proof The Network Sets Your Speed Limit Every database has a ceiling set by the slowest step that cannot run in parallel. Drag the sliders and watch a round-trip architecture hit its wall, while ReifyDB does not. Network round trip 5 ms Contention 10 % Traditional ( [ App ] → [ DB ] → [ App ] ) × N, one round trip per statement. 2.0k TPS Ceiling, engine capped at 100.0k TPS ReifyDB [ App ] → [ N statements, one ACID transaction ] → [ ReifyDB ], no round trips. 100.0k TPS Actual, unaffected by round trips or contention The network is the hard limit. ReifyDB eliminates round trips from the hot path. Use Cases Built for Live Application State If your application reads it, writes it, and reasons about it on every request, that is the state ReifyDB was built for. Trading & Financial State Positions, balances, order state. One bad write here can cost real money. ReifyDB makes sure that does not happen. Game & Simulation State Player state, world state, simulation ticks. Everything stays consistent even when thousands of updates hit at once. Workflow & Process State Multi-step workflows, task queues, process coordination. No more duct-taping Redis, Postgres, and a cron job together. Counters, Queues & Buffers Counters, ring buffers, histograms, rate limiters. Built in, transactional, and ready to use. No external dependencies. FAQ Frequently Asked Questions Honest answers to the questions engineers actually ask What is ReifyDB? ReifyDB is a database for application state. It helps you understand, mutate, and derive live application state under a single transactional model. State is kept in memory for low latency, persisted asynchronously for durability, and extended with application-defined logic that runs next to the data. Clients authenticate as themselves, and policies decide per user what may be read and written. How is ReifyDB different from PostgreSQL or Redis? PostgreSQL is disk-first: durable and query-rich, but slow for real-time state. Redis is memory-first: fast, but transactions lack rollbacks and there is no derived state. ReifyDB is designed around reasoning about state - with full ACID transactions, plus incremental materialized views and programmable logic that runs inside the database. Is ReifyDB production ready? No. ReifyDB is in active development. APIs and guarantees may change. I recommend using it for experimentation and development, but not for production workloads yet. View All FAQs → Still have questions? Ask on Discord → One database instead of Postgres + Redis + a queue + a cron job. Version 0.9. Not production ready, and every page says so. Read the docs, run the examples in the playground, and see if it fits your workload. Read the Docs Read the Manifesto View on GitHub ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/blog/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started blog::posts from blog :: posts sort { date : desc } head @ #002 · 2 entries ▸ #002 2026-08-12 The Cron Job You Deleted 9 MIN Refresh jobs exist because the database could not keep a number current. Incremental views remove the job. BLOOM 002 8e5c01 Contents 01 What Stale Actually Costs 02 The View Is The Query 03 Nothing Refreshes It 04 One Row In, One Row Out 05 The Number Can Go Down 06 Membership Is Not Decided At Insert 07 A Row Can Change Groups 08 Delete Is The Same Machinery 09 Closing author Dominique size 6.8 KB read 9 MIN # buildinpublic Read entry  → fsync #002 · 6.8 KB ▸ #001 2026-08-05 Introducing ReifyDB 10 MIN A programmable, incremental database built for live systems. BLOOM 001 bc115c Contents 01 The Problem: State Is Not Static 02 What Is ReifyDB? 03 Core Concepts 04 Why Not Just Use Postgres? 05 Architecture Philosophy 06 Closing author Dominique size 3.7 KB read 10 MIN # database # realtime # dataengineering Read entry  → ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/blog/introducing-reifydb/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started ← Back to log · Introducing ReifyDB #001 2026-08-05 10 MIN Dominique 3.7 KB Introducing ReifyDB A programmable, incremental database built for live systems. Most databases were designed for one of two worlds. OLTP gives you fast writes, simple queries, and transactional integrity. OLAP gives you large scans, analytics, and heavy aggregations. Modern applications, especially real-time systems, live in both worlds at once. ReifyDB was built for that intersection. The Problem: State Is Not Static If you're building a blockchain indexer, a trading engine, a real-time analytics platform, a reactive backend, or an agent-driven system, you don't just store data. You maintain live, continuously updating state derived from other state. Traditional architecture usually looks like a long chain: source to ETL to database to queue to background jobs to materialized views to cache. Every step is custom code. Every aggregation is recomputed. Every view is fragile. ReifyDB collapses this into a single programmable core. What Is ReifyDB? ReifyDB is a programmable, incremental relational database designed for deterministic updates, real-time materialized views, streaming-first workloads, and columnar execution. At its core, ReifyDB treats computation as dataflow. Instead of recomputing queries from scratch, it propagates only the delta, the change. If one row changes, only the dependent rows update. Core Concepts 1. Incremental Materialized Views Views in ReifyDB are always live. When base data changes, there is no background job, no polling, and no recompute. Only the affected rows update. 2. Columnar Execution (Without Becoming an OLAP Warehouse) ReifyDB stores data in a columnar layout for fast execution, but it is not a batch warehouse. The write path accepts row-based input, immediately transforms it into columnar representation, applies incremental updates, and maintains transactional guarantees. You get OLTP-style updates with OLAP-style execution speed, without running separate systems. 3. Programmable Query Layer ReifyDB exposes a relational query language (RQL). Everything is expressed as queries: tables, views, flows, and derived state. Configuration is code. Deployment is applying the same queries in staging and production. This makes it infrastructure-friendly: version-controlled, deterministic, reviewable, and composable. 4. Designed for Live Systems ReifyDB is optimized for workloads where data arrives continuously, queries must stay up to date, latency matters, and full recompute is unacceptable. Why Not Just Use Postgres? Postgres is excellent. But when your workload becomes highly derived, constantly mutating, dependent on rolling aggregates, and built around live views, you end up building triggers, background jobs, caches, queue consumers, and custom aggregation services. ReifyDB moves that logic into the engine. Architecture Philosophy ReifyDB is built with a few strong principles: incremental by default, columnar for compute and compression, deterministic execution, programmable state, and single-engine simplicity. It avoids recompute-heavy pipelines, cache invalidation nightmares, split OLTP/OLAP stacks, and opaque background jobs. Closing CS 101 says never build your own database. That is solid advice if your goal is a paper. It is worse advice if you've spent years wiring triggers into schedulers, standing up a service whose only job is cache invalidation, and refreshing a materialized view from a cron job nobody trusts. I did not build ReifyDB from a research problem. I built it from an application backlog. Every feature in it exists because the alternative was one more moving part to operate at 3am. Incremental, programmable state should not require five separate systems glued together. If you're building something where data never sleeps, ReifyDB is the thing you were already assembling by hand. ← Back to log share X Telegram Copy link # database # realtime # dataengineering ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/blog/the-cron-job-you-deleted/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started ← Back to log · The Cron Job You Deleted #002 2026-08-12 9 MIN Dominique 6.8 KB The Cron Job You Deleted Refresh jobs exist because the database could not keep a number current. Incremental views remove the job. You have written this cron job. Maybe not this exact one, but this shape: something that wakes up every five minutes, recomputes a number that has been wrong for four of them, and hopes nobody looked. What Stale Actually Costs The refresh job is not the problem. The window is. Between runs, the dashboard is wrong. Not broken, not erroring, just wrong, with a timestamp that looks fresh. You hear about it from someone who trusted it. So the job gets defended. The refresh starts taking longer than the interval, so you add a lock. Two views need it in order, so you add a queue. Something has to drop the cache after the refresh lands, so you write a service whose entire job is knowing which keys to delete. None of that is your product. It is scaffolding around a database that cannot hold a derived number current on its own. And nearly all of the work is waste. One order lands in one region. The refresh rescans every region, re-sums every row ever written, and writes back a result where exactly one number changed. The View Is The Query Start with a table. create namespace shop002; create table shop002::orders { id: int4, region: utf8, total: float4, status: utf8 } Now the revenue rollup, as a view. create deferred view shop002::revenue_by_region { region: utf8, revenue: float4 } as { from shop002::orders filter { status == "paid" } aggregate { revenue: math::sum(total) } by { region } } That is the whole thing. No schedule, no trigger, no worker deployed beside it, no second copy of the aggregation logic living in application code. The query is the definition, and the definition is what runs on every write. Nothing Refreshes It Three orders arrive. Two are paid, one is still pending. insert shop002::orders [ { id: 1, region: "north", total: 120.00, status: "paid" }, { id: 2, region: "south", total: 80.50, status: "paid" }, { id: 3, region: "north", total: 240.00, status: "pending" } ] Read the view. from shop002::revenue_by_region sort { region: asc } Two regions, paid rows only. The pending 240 is not in there, because the filter is part of the view and the filter ran on the way in. Notice what did not happen. No job ran between the insert and the read. Nothing was scheduled, nothing was invalidated, nothing was waiting to catch up. There was no refresh to run, because the view was never behind. One Row In, One Row Out One more paid order, in north only. insert shop002::orders [ { id: 4, region: "north", total: 300.00, status: "paid" } ] Read the view again. from shop002::revenue_by_region sort { region: asc } north moved from 120 to 420. south is untouched, and it was not recomputed to arrive at that. The engine did not rescan orders , did not re-sum rows it had already summed, and did not visit the south group at all. It took one row, worked out which group it belonged to, and adjusted that group. This is the part that matters at scale. With a refresh job, inserting the millionth order costs a scan of a million rows, because the job has no idea what changed and has to assume everything did. Here it costs one row. The work is proportional to the change, not to the size of the table, so the cost of staying current stops growing with your data. The Number Can Go Down Inserts are the easy half. Order 2 was keyed wrong: the total was 180.50, not 80.50. update shop002::orders { total: 180.50 } filter { id == 2 } Read the view. from shop002::revenue_by_region sort { region: asc } south is 180.50 now. north did not move. An update is two changes, not one. The old row leaves the sum and the new row joins it, so the engine subtracts 80.50 from south , adds 180.50, and stops. It did not re-sum the other south rows, and it did not visit north at all. Subtraction is the half a refresh job cannot do. The job keeps no record of what any row contributed, so the only way it can take 80.50 back out of a total is to rebuild that total from zero. That is the real reason refresh cost tracks table size instead of change size. A view that can retract does not have that problem. Membership Is Not Decided At Insert Order 3 was pending, so the view never counted it. It gets paid. update shop002::orders { status: "paid" } filter { id == 3 } from shop002::revenue_by_region sort { region: asc } north went from 420 to 660. A row entered the view without an insert. Now a refund lands on order 1. update shop002::orders { status: "refunded" } filter { id == 1 } from shop002::revenue_by_region sort { region: asc } north dropped to 540. A row left the view without a delete. The filter is not a gate the row passes once on the way in. It is re-tested on every change to that row, and the answer is allowed to flip in both directions. This is the failure that hides in most hand-rolled incremental caches: they add on insert, nobody remembers that status is a column that changes, and the total drifts upward forever because no run ever takes anything back out. A Row Can Change Groups Order 4 was booked against the wrong region. update shop002::orders { region: "south" } filter { id == 4 } from shop002::revenue_by_region sort { region: asc } One row changed and two groups moved. north gave up 300, south took it. The engine did not have to enumerate the regions to work that out, and no third group was touched to confirm it was unaffected. Delete Is The Same Machinery After the refund, north is holding exactly one paid order: id 3. Delete it. delete shop002::orders filter { id == 3 } from shop002::revenue_by_region sort { region: asc } north is not in the result. Not zero, not none , not a leftover row still claiming 240. The group is gone, because the group only ever existed for as long as a row produced it. A delete is the retraction half of an update with nothing added back. Same path, same cost, one row. There is no separate deletion code to write, no tombstone to sweep, and no run to schedule that notices the group emptied out. Closing The refresh job was never a design decision. It was the thing you added because the database could not do this, and then it grew a lock, a queue, a cache invalidator, and a runbook. Every one of those parts exists to compensate for a number that goes stale on its own. A view that updates on write does not need any of them. Delete the job, delete the lock, delete the service that dropped the cache. The aggregation is still there. It just lives in the engine now, next to the data it reads, running on the only three occasions that could ever change the answer: a row arrives, a row changes, a row goes away. For the full mechanics, including when a view becomes visible to a reader and how views compose on top of other views, see Build Incremental Views . ← Back to log share X Telegram Copy link # buildinpublic ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/company/mission/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started The Mission Why? Mission Statement Most engineers have felt it, that moment where you're fighting your own infrastructure instead of building the thing you set out to build. Your database should work with you, not against you. ReifyDB exists because we believe the way you think about your data is the right way to store it, query it, and evolve it. No translation. No friction. Just building. The argument about the problem itself is written down in the manifesto . The Origin Story When Dominique's daughter was born, everything slowed down for a moment. For the first time in years, he stepped back and asked a simple question: what actually makes me happy? And maybe more importantly, what doesn't? The answer was painfully clear. Throughout his career building software, the most frustrating part was always the same: working with data infrastructure. The endless translation between how you think about your domain and how the database forces you to store it. The layers of abstraction that nobody asked for. The friction that quietly drains your energy, sprint after sprint, year after year. Every engineer knows the feeling. You just learn to live with it. Dominique decided to stop living with it. ReifyDB started as a question: what if the database actually worked the way engineers think? No translation layers, no accidental complexity, just infrastructure that gets out of your way and lets you build. That's what ReifyDB is for. ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/company/values/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Values The principles guiding ReifyDB 01 Respect the Developer's Mind You already know how your data fits together. Your database should respect that, not force you to rethink it in a language it invented. The best infrastructure disappears. You stay in flow, building what matters, not wrestling with tooling. 02 Complexity Must Justify Itself If you need a tutorial just to insert a row, something went wrong. Every layer we add has to earn its place. If a feature feels complicated, we are not done building it yet. The right answer should feel obvious. 03 Correctness Is a Feature Speed is great until your data is wrong. We build for the workloads where mistakes compound, where one bad write can cascade through an entire system. You should not have to choose between fast and correct. You get both. 04 Truth Over Theater Not every workload belongs in ReifyDB, and we will tell you that upfront. We would rather lose a sale than waste your time. Clear boundaries build more trust than big promises, and honest software outlasts hype every time. 05 Software Is a Long-Term Relationship You are going to build on top of ReifyDB for years. We take that seriously. Stability, backward compatibility, and predictable upgrades matter more than chasing the latest trend. Your infrastructure should get better with time, not rot under you. ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/contact/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Get in Touch Whether you have questions about ReifyDB or want to discuss your use case, I'd love to hear from you. Book a Call Schedule a 30-minute call to discuss ReifyDB, your use case, or explore how ReifyDB can help. Schedule a Call Email founder@reifydb.com GitHub Open an issue Discord Join the community ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL Introduction Quickstart ← Back Docs / Getting Started ReifyDB Documentation Your database should work the way you think. ReifyDB does. ReifyDB is a database for live application state. You get transactional guarantees, incremental derived views, programmable state transitions, and per-user access rules in one coherent system. In Development ReifyDB is under active development. Do not use in production yet. APIs and guarantees may change. What is ReifyDB? You have probably split your application state across a database, a cache, a queue, and maybe an in-memory store. ReifyDB brings all of that into one system. Live application state is the data your application reads, writes, and reasons about on every request. User sessions, shopping carts, account balances, game state. The stuff that has to be right. You get ACID transactions, materialized views that stay fresh automatically, and a query language (RQL) built for the way you actually work with state. Get Started Quickstart Build a live view in your browser, nothing to install. → RQL in Five Minutes Learn the query language, one runnable concept at a time. → Installation Get ReifyDB running for real, embedded or as a server. → Key Features -- Transactional - Your application state stays consistent. Full ACID guarantees, real rollback. -- Incremental - Your views update the moment your data changes. No cron, no polling. -- Embeddable - Embed it in your app or run it as a standalone server. Your call. -- RQL - A query language that fits how you think about your data, not how a database thinks about tables. Resources GitHub Repository → Discord Community → Contact Me → Next → Quickstart ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/concepts/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL What ReifyDB Is Data Model Namespaces Tables Transactions ← Back Docs / Concepts / What ReifyDB Is The database that runs your backend logic. ReifyDB stores, mutates, and derives live application state under one transactional model. State lives in memory for low latency, is persisted asynchronously for durability, and every query runs as the user who asked: authentication and policies live in the database, next to the rules they protect. The problem it replaces Most applications fragment their state across systems: a database for persistence, a cache for speed, and background workers that keep derived data fresh. Each seam adds failure modes - cache invalidation bugs, stale read models, polling jobs that recompute what a write already knew. ReifyDB collapses those layers into one engine: tables hold authoritative state, and views derive from them incrementally as data changes. Run the snippets on this page in order. First, a table and two views that aggregate it - one transactional , one deferred : A Table and Two Views Derived From It create namespace cpt; create table cpt::orders { id: int4, region: utf8, total: float8 }; create transactional view cpt::revenue_by_region { region: utf8, revenue: float8 } as { from cpt::orders aggregate { revenue: math::sum(total) } by { region } }; create deferred view cpt::order_count { orders: int8 } as { from cpt::orders aggregate { orders: math::count(id) } by {} } Now write to the table. There is no second system to notify and no refresh job to schedule: Write to the Table insert cpt::orders [ { id: 1, region: "North", total: 120.0 }, { id: 2, region: "South", total: 80.0 }, { id: 3, region: "North", total: 45.5 } ] The transactional view was maintained by the write itself. Reading it costs a lookup, not a recomputation: The View Is Already Current from cpt::revenue_by_region sort { region: asc } Transactional or deferred The two views above are kept fresh in different ways, and the difference is the main decision you make per view. A transactional view is maintained inside the writing transaction: when the commit returns, the view is already correct, at the cost of doing that work on the write path. A deferred view is maintained asynchronously from the change stream after the commit: writes stay cheap, and the view catches up moments later - it is eventually consistent. The Deferred View Caught Up from cpt::order_count Use transactional views for derived state that reads must never see stale - balances, inventory, anything an invariant depends on. Use deferred views when a moment of lag is fine and write latency matters - dashboards, counters, feeds. See Views for the full comparison. State first, queries second In ReifyDB, state is the primary concept and queries are secondary. Tables represent authoritative state; views represent derived state, not reports - you choose per view how fresh it must be. Alongside tables and views, the engine has specialized state shapes - ring buffers, series, dictionaries - so state that would otherwise live in Redis or a custom service participates in the same transactions. A ring buffer, for example, is bounded state with eviction built in: A Ring Buffer Keeps the Last N Rows create namespace cpt_rb; create ringbuffer cpt_rb::recent_logins { user_id: int4, at: utf8 } with { capacity: 3 }; insert cpt_rb::recent_logins [ { user_id: 1, at: "09:00" }, { user_id: 2, at: "09:05" }, { user_id: 3, at: "09:12" }, { user_id: 4, at: "09:20" } ]; from cpt_rb::recent_logins Four rows were inserted into a buffer with capacity three; the oldest was evicted. No cleanup job required. In-memory, asynchronously durable All state changes go through transactions, and a committed change is visible immediately - but the commit does not wait for disk. Persistence happens off the hot path with bounded latency, and recovery rebuilds state deterministically from durable storage. That trade is deliberate. Application state is read and written on every request, so ReifyDB prioritizes predictable low latency over synchronous durability on each individual write. See Durability & Storage for what this means for crash recovery. What ReifyDB is not ReifyDB manages the live, mutable state your application reasons about on every request. It is not a BI warehouse and not an analytics engine for ad-hoc queries over cold historical data. Those workloads have different trade-offs and belong in different systems. Where to go next -- Quickstart - build a live view and watch it maintain itself -- RQL in Five Minutes - the pipeline query language used on this page -- Data Model - namespaces, tables, and the specialized state shapes -- Views - transactional vs deferred views in depth -- Transactions - the model every state change goes through The database knows who is asking ReifyDB runs embedded in your application or as a server that clients connect to over WebSocket or HTTP. Every connection authenticates as a named identity, and roles and policies decide what that identity may read and write. Clients talk to ReifyDB directly; there is no layer in front holding a shared password or a second copy of the access rules. ← Previous Quickstart Next → Data Model ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/concepts/data-model/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL What ReifyDB Is Data Model Namespaces Tables Transactions ← Back Docs / Concepts / Data Model Data Model ReifyDB models application state with a small set of purpose-built primitives instead of tables-for-everything. Each storage shape has distinct semantics - how rows are kept, ordered, evicted, or derived - and all of them participate in the same transactions. This page is the map; every primitive has its own page with runnable examples. Namespaces organize everything Every object lives in a namespace and is addressed as namespace::object , for example shop::orders . Namespaces nest, isolate names, and are the natural boundary for environments and tenants. The engine's own catalog is exposed the same way, under system::* . The storage shapes Six shapes hold rows. Two store what your application asserts, three specialize how state is kept, and one derives state from the others: -- Tables - authoritative, mutable state; the primary shape. Typed columns, optional columns, auto-increment, primary keys, in-place schema evolution. -- Views - derived state the engine maintains incrementally. Transactional (correct at commit) or deferred (catches up moments later), materialized into table, ring buffer, or series storage. -- Ring Buffers - fixed capacity, oldest row evicted when full; optionally one buffer per partition key. "Keep the last N" without cleanup jobs. -- Series - rows ordered by a required time or integer key. Measurements, audit trails, historical records; range queries follow the key. -- Dictionaries - value interning: strings stored once, referenced by compact IDs, wired into table columns transparently. Reacting to change -- Subscriptions - an append-only change stream over a source, tagged insert / update / delete; what a live frontend consumes. -- Events - declared domain events with typed payloads, dispatched inside a transaction. -- Handlers - reactions bound to event variants; they run synchronously in the dispatching transaction and can chain further dispatches. -- Procedures - named, callable logic stored next to the data: typed parameters, scripted bodies, in-database tests. Types and identity -- Enums - closed variant sets as column types, with optional payload fields. -- Tags - variant sets that classify series entries. -- Sequences - the counters behind auto-increment columns; inspectable and repositionable. Access control Because clients query the database directly, policies replace the API layer as the place where access rules live: row filters, column masks, and write constraints per identity, attached to tables, views, namespaces, sessions, and procedures. Non-root identities are denied by default. Where to start If you are new to ReifyDB, read Tables and Views first - together they carry most applications. Reach for the specialized shapes when a table plus application code starts reimplementing eviction, ordering, or interning by hand. ← Previous What ReifyDB Is Next → Namespaces ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/concepts/data-model/namespaces/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL What ReifyDB Is Data Model Namespaces Tables Transactions ← Back Docs / Concepts / Data Model / Namespaces Namespaces Namespaces organize every other object in ReifyDB. Tables, views, ring buffers, series, dictionaries, and types all live inside a namespace and are addressed as namespace::object . A namespace must exist before you can create objects in it. Creating a namespace create namespace registers the container; from then on, every reference to an object inside it uses the :: separator. Run the snippets on this page in order: Create a Namespace and Address Objects Inside It create namespace dm_ns; create table dm_ns::users { id: int4, name: utf8 }; insert dm_ns::users [{ id: 1, name: "Ada" }]; from dm_ns::users Names are scoped, not global Two namespaces can hold objects with the same name without conflict. This is the natural way to separate environments, tenants, or subsystems inside one database: prod::orders and staging::orders are entirely distinct tables. The Same Object Name in Two Namespaces create namespace dm_ns_prod; create namespace dm_ns_staging; create table dm_ns_prod::orders { id: int4 }; create table dm_ns_staging::orders { id: int4 }; insert dm_ns_prod::orders [{ id: 1001 }]; insert dm_ns_staging::orders [{ id: 1 }]; from dm_ns_prod::orders Idempotent creation if not exists makes creation safe to re-run, which matters for setup scripts and migrations. The result reports created: false when the namespace was already there: Idempotent Creation with IF NOT EXISTS create namespace dm_ns if not exists Nested namespaces Namespaces nest. Creating dm_ns::internal places a child namespace under dm_ns , and objects inside it are addressed with the full path, for example dm_ns::internal::audit . Use nesting to group related state without inventing name prefixes: Nested Namespaces create namespace dm_ns::internal; create table dm_ns::internal::audit { id: int4, action: utf8 }; insert dm_ns::internal::audit [{ id: 1, action: "login" }]; from dm_ns::internal::audit Inspecting namespaces The system catalog is itself queryable. system::namespaces lists every namespace with its full name, its local name, and the id of its parent - nested namespaces show up as children of the namespace that contains them: Inspect Namespaces via the System Catalog from system::namespaces filter { local_name == "internal" } The system namespace also exposes system::tables , system::views , system::policies , and storage metrics. Reads on system::* are policy-gated for non-root identities. Where to go next -- Tables - the primary shape for authoritative state -- Policies - control what each identity may read and write, per namespace or per object -- Data Model overview - all primitives at a glance Reserved namespaces ReifyDB reserves a few namespaces for itself, most visibly system (the queryable catalog) and default . Your application namespaces live alongside them. ← Previous Data Model Next → Tables ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/concepts/data-model/tables/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL What ReifyDB Is Data Model Namespaces Tables Transactions ← Back Docs / Concepts / Data Model / Tables Tables Tables hold authoritative, mutable state - the facts your application asserts directly. They are the primary storage shape: rows are inserted, updated, and deleted transactionally, and everything derived (views, subscriptions) ultimately sources from them or from the other storage shapes. Creating a table A table is a named set of typed columns inside a namespace . Column types include integers ( int1 through int16 , uint1 through uint16 ), floats ( float4 , float8 ), bool , strings ( utf8 , with text as an alias), blob , and temporal types ( date , time , datetime , duration ). See Data Types for the full list. Run the snippets on this page in order: Create a Table and Insert Rows create namespace dm_tbl; create table dm_tbl::products { id: int4, name: utf8, price: float8, discontinued: bool }; insert dm_tbl::products [ { id: 1, name: "Widget", price: 9.99, discontinued: false }, { id: 2, name: "Gadget", price: 24.5, discontinued: false } ]; from dm_tbl::products Reads return the newest rows first by default; add sort for an explicit order. Optional columns Columns are non-nullable unless declared Option(type) . An optional column that was never set holds none - ReifyDB's explicit absent value, which queries can test for and which renders distinctly in results. See Working with none . Optional Columns Hold none create table dm_tbl::customers { id: int4, name: utf8, referral: Option(utf8) }; insert dm_tbl::customers [ { id: 1, name: "Ada", referral: "friend" }, { id: 2, name: "Grace" } ]; from dm_tbl::customers Auto-increment columns An integer column declared with { auto_increment } is assigned the next value of a per-column sequence on insert, so writers never need to coordinate IDs. The sequence itself can be inspected and repositioned - see Sequences . Auto-Increment Columns create table dm_tbl::tickets { id: int8 with { auto_increment }, title: utf8 }; insert dm_tbl::tickets [{ title: "First" }, { title: "Second" }]; from dm_tbl::tickets Primary keys A primary key is declared as a separate statement after the table exists, and can span multiple columns: create primary key on ns::table { col1, col2 } . Define a Primary Key create table dm_tbl::accounts { id: int4, owner: utf8 }; create primary key on dm_tbl::accounts { id } Updating and deleting update sets the listed fields and leaves every other column untouched; delete removes whatever matches the filter. Both take a filter to select rows, and both accept returning to hand back the affected rows in the same statement - useful when the write itself computes something you need, like a generated ID or the post-update value: Update Rows and Return the Result update dm_tbl::products { price: 19.99 } filter { name == "Gadget" } returning { id, name, price } Without returning , mutations report what happened as a count: Delete Rows by Predicate update dm_tbl::products { discontinued: true } filter { id == 1 }; delete dm_tbl::products filter { discontinued == true } System columns Every stored row carries engine-maintained columns prefixed with # . They are not returned by default; project them explicitly when you need them. #rownum is the row's stable number within its table: System Columns from dm_tbl::customers map { row: #rownum, name } Evolving the schema alter table adds and drops columns in place. Add new columns as Option(type) when existing rows have no value for them: Evolve the Schema with ALTER TABLE alter table dm_tbl::customers add column email: Option(utf8) When a table is not the right shape -- Bounded recent history with automatic eviction: use a ring buffer -- Time-ordered measurements and audit records: use a series -- Repeated low-cardinality strings: intern them with a dictionary -- State computed from other state: never write it by hand - derive it with a view Row lifetime Tables keep rows until you delete them. To expire rows by age instead, attach a TTL - see TTL & Row Settings . ← Previous Namespaces Next → Transactions ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/concepts/transactions/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL What ReifyDB Is Data Model Namespaces Tables Transactions ← Back Docs / Concepts / Transactions Transactions Every request you send to ReifyDB runs inside a transaction, automatically. Writes commit atomically with serializable snapshot isolation, reads see a consistent snapshot, and conflicts are retried for you. There is no BEGIN , COMMIT , or ROLLBACK to manage - transaction handling is the engine's job, not yours. Queries, commands, and admin ReifyDB splits work into three kinds of transactions, and the clients expose them as three entry points: -- A query transaction ( query ) only reads. It runs under snapshot isolation : it pins the latest committed state when it starts and sees exactly that state for its entire run - never a half-applied write, no matter how many writers are active. -- A command transaction ( command ) writes data: inserts, updates, deletes, procedure calls. It runs under serializable snapshot isolation - the engine tracks what each command reads and writes, and only lets it commit if the result is equivalent to the commands running one after another. A command cannot change schema. -- An admin transaction ( admin ) is the only kind that can execute DDL - create , alter , drop , migrations, access control. It can also write data, so a schema change and the writes that go with it commit as one atomic unit. Keeping schema changes out of command transactions means day-to-day application traffic physically cannot alter the schema - evolving it is a deliberate, separately privileged operation. There is no isolation level to configure and no weaker mode to fall back to. One request, one transaction Each request is exactly one transaction. A request may contain many statements - they all commit together, or none of them do. This transfer touches two rows in two separate update statements, and no reader can ever observe the state between them (the runnable snippets on this page execute as admin requests, which is why they can mix create statements with writes): A Multi-Statement Command Commits Atomically create namespace txn; create table txn::accounts { id: int4, owner: utf8, balance: int8 }; insert txn::accounts [ { id: 1, owner: "ada", balance: 100 }, { id: 2, owner: "grace", balance: 50 } ]; update txn::accounts { balance: 75 } filter { owner == "ada" }; update txn::accounts { balance: 75 } filter { owner == "grace" }; from txn::accounts sort { id: asc } If any statement fails, the whole request rolls back. Here the update executes first and the cast fails afterwards: An Error Rolls Back the Whole Request update txn::accounts { balance: 0 } filter { owner == "ada" }; map { oops: cast("not a number", int4) } The update was rolled back with everything else - the balances are untouched: Nothing Was Applied from txn::accounts sort { id: asc } No BEGIN, no COMMIT - by design ReifyDB has no statement to hold a transaction open across requests. Frontends talk to the database directly, and an open transaction owned by a browser tab is a liability: it pins resources until a client that may have disappeared decides to finish it. Bundling each request into one atomic transaction removes that failure mode and is what makes automatic conflict retry safe - nothing is committed until the whole request succeeds. The rollback keyword you may encounter in migrations is unrelated: it declares compensating statements for reverting a migration, not transaction control. Readers never block writers ReifyDB uses multi-version concurrency control (MVCC). Every commit produces a new version of the rows it touched instead of overwriting them in place, and every committed transaction is stamped with a monotonically increasing commit version. A query simply reads as of the newest committed version at the moment it starts. It takes no locks, blocks no command, and is blocked by none - long analytical reads and high-frequency writes coexist without queueing on each other. Conflicts and automatic retries Commands are optimistic: they do not lock rows up front. Instead, each command works against its own snapshot, and at commit the engine validates that no other transaction has committed a change that overlaps with what this command read or wrote. If validation fails, the command aborts with a conflict error ( TXN_001 ) - and the server retries it automatically with backoff, up to 10 attempts by default. Each retry re-executes the request from scratch against the newest state, so the retried command sees the data that beat it to the commit. In practice you rarely see conflicts at all: queries never conflict with anything, and commands only conflict when they genuinely race over the same data. If a command still fails with TXN_001 after all retries, the client receives the error and can decide whether to resubmit. Views, handlers, and transactions Derived state participates in the same guarantees. Transactional views are maintained inside the commit of the write that affects them - the table and the view change in the same atomic step: A Transactional View over a Table create table txn::orders { id: int4, total: int8 }; create transactional view txn::revenue { revenue: int8 } as { from txn::orders aggregate { revenue: math::sum(total) } by {} } Write to the source table: Write to the Source Table insert txn::orders [{ id: 1, total: 40 }, { id: 2, total: 25 }] The view is already current - there is no window in which the table shows the new order but the view shows the old revenue: The View Committed with the Write from txn::revenue That timing has one consequence worth knowing: once a request writes to a view's source data, reading that view later in the same request is an error ( TXN_015 ), and the whole request fails and rolls back. Mid-request the view still holds its pre-request contents, and ReifyDB fails loudly rather than hand you stale data: Write Then Read the View in One Request insert txn::orders [{ id: 3, total: 10 }]; from txn::revenue The failed request committed nothing, and reading the view in its own request works as before: The Failed Request Left Nothing Behind from txn::revenue The rule applies to transactional and deferred views alike, and it follows view chains - a view built on top of another view is protected too. Reading a view before writing to its sources is fine. The remedy depends on the view kind: a transactional view is current the moment the write returns, so split the write and the read into separate requests, or read the source tables directly. A deferred view updates asynchronously after commit, so read the source tables directly, or consume the view through a subscription : A Deferred View over the Same Table create deferred view txn::order_count { orders: int8 } as { from txn::orders aggregate { orders: math::count(id) } by {} } Writing upstream of the deferred view and reading it in the same request fails the same way: Deferred Views Are Protected Too insert txn::orders [{ id: 3, total: 10 }]; from txn::order_count Handlers run synchronously inside the writing transaction too - if a handler fails, the write that triggered it rolls back. Deferred views and subscriptions are the asynchronous side: they consume committed changes after the fact, ordered by commit version, and are eventually consistent. Under the hood A command buffers its writes locally and records the keys and ranges it reads. At commit, a central coordinator checks that read/write set against every transaction that committed since the command's snapshot; if nothing overlaps, it allocates the next commit version and publishes the write-set - to storage, to transactional view maintenance, and to the change log that feeds subscriptions, all under that one version. For the full mechanics - the commit pipeline, conflict windows, and watermarks - see Transaction Internals . Commit and the disk Committed data is immediately visible to every subsequent transaction, and is persisted to disk asynchronously. What that means for crash recovery is covered in Durability & Storage . ← Previous Tables Next → RQL in Five Minutes ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/quick-start/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL Introduction Quickstart ← Back Docs / Getting Started / Quickstart Quickstart Create a table, define a live view over it, and watch ReifyDB keep that view up to date as the data changes. Right here in your browser, nothing to install. This page is a real database Every snippet below runs against a real ReifyDB engine compiled to WebAssembly. Click Run on each snippet, top to bottom. You can edit any of them. 1. Create a table Tables hold authoritative state. Every table lives in a namespace and is addressed as namespace::table : Create a Table create namespace shop; create table shop::orders { id: int4, item: utf8, amount: float8, status: utf8 } 2. Define a live view A transactional view is derived state. You declare the query once; ReifyDB maintains the result incrementally, inside the same transaction as every write that affects it. No polling, no cache invalidation, no batch refresh: Create a Transactional View create transactional view shop::open_orders { id: int4, item: utf8, amount: float8 } as { from shop::orders filter { status == "open" } map { id, item, amount } } The view tracks changes from the moment it is created, so we define it before inserting data. 3. Insert rows INSERT takes an array of records: Insert Rows INSERT shop::orders [ { id: 1, item: "keyboard", amount: 89.0, status: "open" }, { id: 2, item: "monitor", amount: 349.5, status: "open" }, { id: 3, item: "cable", amount: 12.5, status: "shipped" }, { id: 4, item: "desk", amount: 420.0, status: "shipped" } ] 4. Query the table RQL queries are pipelines. Start with from , then chain steps; each line transforms the output of the line above it: Query the Table from shop::orders filter { status == "open" } sort { id: asc } 5. Query the view The view already contains the two open orders. Nothing recomputed the query; the inserts themselves maintained it: Query the View from shop::open_orders sort { id: asc } 6. Change the data Ship the keyboard order: Update a Row UPDATE shop::orders { status: "shipped" } FILTER { id == 1 } Then query the view again. The shipped order is gone, because the view's filter no longer matches it: The View Maintained Itself from shop::open_orders sort { id: asc } 7. Aggregate Pipelines end wherever you need them to. Group and aggregate with aggregate ... by : Aggregate Revenue by Status from shop::orders aggregate { revenue: math::sum(amount), orders: math::count(id) } by { status } sort { status: asc } Where next -- RQL in five minutes - the query language, one concept at a time -- Installation - run ReifyDB for real, embedded or as a server -- Concepts - what an application state database is and when to use one ← Previous Introduction Next → What ReifyDB Is ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/rql/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL RQL in Five Minutes RQL for SQL Users ← Back Docs / RQL / RQL in Five Minutes RQL in Five Minutes RQL is ReifyDB's query language. A query is a pipeline: it starts from data and flows top to bottom, one transformation per line. Every snippet on this page runs in your browser. The pipeline from names the source. filter keeps matching rows. map picks the shape of the output. sort orders it. Each step consumes the previous step's rows, so you read a query the same way it executes: pipeline from app::users | v filter { active == true } | v map { name, email } | v sort { name: asc } A Complete Pipeline from app::users filter { active == true } map { name, email } sort { name: asc } There is no SELECT in RQL, and no inside-out reading order. Start from any data A pipeline usually starts from a table or view, but it can start from inline records too. Handy for prototyping an expression before you have a schema: Query Inline Data from [ { name: "Ada", born: 1815 }, { name: "Grace", born: 1906 }, { name: "Edsger", born: 1930 } ] sort { born: asc } Shape rows with map map selects columns and computes new ones. take caps the result. Combined with sort , that is SQL's SELECT ... ORDER BY ... LIMIT in three readable lines: Shape Rows with map from [ { item: "keyboard", amount: 89.0 }, { item: "monitor", amount: 349.5 }, { item: "desk", amount: 420.0 } ] map { item, amount, with_shipping: amount + 4.5 } sort { amount: desc } take 2 Aggregate by group aggregate ... by groups rows and reduces each group. Aggregation functions are namespaced, like everything callable in RQL: math::sum , math::avg , math::count : Aggregate by Group from [ { region: "north", amount: 120.0 }, { region: "north", amount: 80.0 }, { region: "south", amount: 200.5 } ] aggregate { total: math::sum(amount), sales: math::count(amount) } by { region } sort { region: asc } An empty by {} aggregates the whole input into a single row. Missing values are none RQL has no null. A missing value is written none , and it is typed: a missing int4 is still an int4 . Arithmetic propagates it instead of failing: none Propagates Through Arithmetic from [ { id: 1, score: 10 }, { id: 2, score: none } ] map { id, doubled: score * 2 } sort { id: asc } Test for it explicitly with is::some and is::none : Filter Out Missing Values from [ { id: 1, score: 10 }, { id: 2, score: none } ] filter { is::some(score) } Variables let binds a value you can reuse anywhere in the statement. RQL also has control flow ( if , loop , match ) for scripting beyond single queries: Variables with let let $threshold = 30; from app::users filter { age >= $threshold } map { name, age } sort { age: desc } Where RQL goes further The same pipeline syntax defines derived state that ReifyDB maintains for you: transactional and deferred views, windowed aggregation over live data, and rows that expire via TTL. That is the point of an application state database: queries you would otherwise re-run become state the database keeps current. -- Quickstart - build a live view and watch it maintain itself -- RQL for SQL users - a direct translation table from SQL -- Pipeline operators - the full operator reference Terminology RQL is not a SQL dialect. Keywords are case-insensitive, statements are separated by semicolons, and the missing value is always called none. ← Previous Transactions Next → RQL for SQL Users ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/docs/rql/for-sql-users/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Getting Started Concepts RQL RQL in Five Minutes RQL for SQL Users ← Back Docs / RQL / RQL for SQL Users RQL for SQL Users Everything you know about querying still applies; the syntax reads in a different direction. SQL describes the result you want from the inside out. RQL describes the steps to get there, top to bottom. Translation table SQL RQL SELECT name, email FROM users from app::users map { name, email } WHERE role = 'admin' filter { role == "admin" } ORDER BY name ASC sort { name: asc } LIMIT 10 take 10 GROUP BY region aggregate { total: math::sum(amount) } by { region } SELECT DISTINCT category distinct { category } NULL none INSERT INTO t VALUES (1, ...) INSERT app::t [{ id: 1, ... }] UPDATE t SET x = 1 WHERE id = 2 UPDATE app::t { x: 1 } FILTER { id == 2 } DELETE FROM t WHERE id = 2 DELETE app::t FILTER { id == 2 } There is no SELECT keyword in RQL. Projection is a pipeline step ( map ), not the frame of the whole query. Reading order A SQL query nests: SELECT ... FROM (SELECT ... FROM t WHERE ...) WHERE ... . The equivalent RQL is flat; each line is one step, and intermediate results never need names: SELECT Becomes a Pipeline from app::users filter { role == "admin" } map { name, email } sort { name: asc } GROUP BY becomes aggregate ... by The aggregation expressions and the grouping keys live in one step. Nothing like HAVING is needed; a filter after the aggregate does the same job: GROUP BY Becomes aggregate ... by from [ { category: "book", price: 12.0 }, { category: "book", price: 8.0 }, { category: "game", price: 60.0 } ] aggregate { avg_price: math::avg(price) } by { category } sort { category: asc } none is not NULL, mostly RQL's missing value is none . Like SQL's NULL, it never matches an equality comparison: Comparing to none Never Matches from [ { id: 1, nickname: "Al" }, { id: 2, nickname: none } ] filter { nickname == none } Unlike SQL, the test for it is an ordinary function, not special syntax ( IS NULL ). And none is typed: a missing int4 still participates in type checking as an int4 : Test for none with is::none from [ { id: 1, nickname: "Al" }, { id: 2, nickname: none } ] filter { is::none(nickname) } What has no SQL equivalent -- Transactional views - materialized views maintained inside the writing transaction, not on a refresh schedule -- Scripting - variables, control flow, and tests in the same language as queries -- Arithmetic with explicit overflow policy - math::add_saturate , math::add_none , and friends make numeric edge cases a choice instead of a surprise Try the full tour RQL in five minutes walks the pipeline model end to end with runnable snippets. ← Previous RQL in Five Minutes ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/examples/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Examples Built-in Testing Browse examples Built-in Testing Define and run tests inside the database ReifyDB has built-in testing primitives. Use CREATE TEST PROCEDURE to define reusable setup logic, and CREATE TEST to write assertions against your data using pipeline syntax. Run all tests in a namespace with RUN TESTS . Each test runs in its own transaction that is rolled back afterward, so tests never interfere with each other or leave behind state. Built-in Testing CREATE NAMESPACE IF NOT EXISTS tp; CREATE TABLE IF NOT EXISTS tp::users { id: int4, name: utf8 }; CREATE TEST PROCEDURE tp::seed_users AS { INSERT tp::users [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]; }; CREATE TEST tp::can_query { CALL tp::seed_users(); FROM tp::users | ASSERT { id > 0 }; }; CREATE TEST tp::can_filter { CALL tp::seed_users(); FROM tp::users | FILTER name == 'Alice' | ASSERT { id == 1 }; }; RUN TESTS tp | map { name, namespace, outcome, message }; ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 Examples Built-in Testing =============================================================================== URL: https://reifydb.com/faq/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Frequently Asked Questions Common questions about ReifyDB > What is ReifyDB? [ + ] ReifyDB is a database for application state. It helps you understand, mutate, and derive live application state under a single transactional model. State is kept in memory for low latency, persisted asynchronously for durability, and extended with application-defined logic that runs next to the data. Clients authenticate as themselves, and policies decide per user what may be read and written. > How is ReifyDB different from PostgreSQL or Redis? [ + ] PostgreSQL is disk-first: durable and query-rich, but slow for real-time state. Redis is memory-first: fast, but transactions lack rollbacks and there is no derived state. ReifyDB is designed around reasoning about state - with full ACID transactions, plus incremental materialized views and programmable logic that runs inside the database. > Is ReifyDB production ready? [ + ] No. ReifyDB is in active development. APIs and guarantees may change. I recommend using it for experimentation and development, but not for production workloads yet. > What is the licensing model? [ + ] ReifyDB is licensed under Apache 2.0. You are free to use, modify, and distribute it under the terms of the license. > Can I embed ReifyDB in my application? [ + ] Yes. ReifyDB can run embedded in your application process or as a standalone server. This is similar to how SQLite or DuckDB work - you choose the deployment model that fits your architecture. > What languages are supported? [ + ] ReifyDB is written in Rust with a native Rust API. TypeScript/JavaScript clients are available for web and Node.js applications. More language bindings are planned. > Why should I trust a new database? [ + ] ReifyDB is open source under Apache 2.0, so you can inspect every line. The core is written in Rust for memory safety and performance. Development is active and transparent on GitHub. > What can I use ReifyDB for today? [ + ] ReifyDB is suitable for prototyping, internal tools, and non-critical workloads where you want to explore the programming model. Use it to build proofs-of-concept, understand incremental derived state, or experiment with colocating logic and data. Wait for a stable release before using it for production systems. ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/manifesto/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Manifesto The Postgres + Redis + cron stack is a bug, not an architecture. Nobody designs it. Everybody ends up with it. This is why, and what should replace it. You have built this. You have a database. It holds the truth. Then the product needed to be fast, so the hot rows got copied into Redis. Then a dashboard needed a total, so a cron job started recomputing it every five minutes. Then a rule had to run when an order changed, so it moved into a worker behind a queue. Then something had to know which cache key to delete when the row changed, so you wrote that too. And all of it connects to the database as one account, with one password, so the code in front decides on behalf of every user what they may see. None of these were mistakes. Each one was the reasonable next step. Look at the whole thing and it is five systems holding one application's state, held together by code whose only job is keeping them from disagreeing. When they do disagree, and they do, the database says one thing, the cache says another, the dashboard says a third, and all three carry a fresh timestamp. You did not architect that. You accumulated it. Today +---------------+ | POSTGRES | +---------------+ ~ glue ~ +---------------+ | REDIS | +---------------+ ~ glue ~ +---------------+ | CRON | +---------------+ ~ glue ~ +---------------+ | QUEUE | +---------------+ ~ glue ~ +---------------+ | WORKERS | +---------------+ five systems, one state | v With ReifyDB +---------------+ | REIFYDB | | | | tables | | views | | transitions | | primitives | +---------------+ one system, one transaction Every box is an apology. Each system in that stack exists because the database could not do one specific thing. Read them as what they are: workarounds, each with a cost you pay every day. [ REDIS ] The hot copy. The database could not serve these rows fast enough, so now there are two of them. One is right. [ CRON ] The refresh. The database could not keep a derived number current, so it is recomputed on a timer. Between runs it is wrong, and it looks fresh. [ QUEUE + WORKERS ] The rule, later. The database could not run your logic when the data changed, so the logic runs afterwards, elsewhere, and hopes the data has not moved. [ SERVICE ACCOUNT ] The one password. The database could not tell your users apart, so everything connects as one privileged account and the code in front of it decides who may do what. Every rule lives twice, one connection can do anything, and queries get built from user input on the way through. [ GLUE ] The code that knows. None of the above knows about the others, so you wrote the code that does. It is the most fragile code you own, and it ships no feature. How it got this way. Databases were built to be systems of record. Write it down, get it back, keep it safe. That was the job, and they are very good at it. But the state an application reasons about on every request is not a record. It is a balance that moves with every trade. A player position that changes every tick. A workflow that is in exactly one step. A rate limit that is either exceeded or not. It is live, it is derived, and it is bound by rules. Nothing in the record model holds that, so it was pushed out of the database, one piece at a time, into the stack above. Databases became systems of record. Applications need systems of live state. What ReifyDB is built on. 01 Derived state is the database's job. If a number can be computed from your data, you should never maintain it by hand. Not with a cron job, not with a cache key, not with a worker that hopes it ran in time. The write that changes the data is the thing that updates the number. 02 A rule enforced in a service is a rule enforced sometimes. Say a balance may never go below zero. If that check lives in a service, it holds only for writes that go through that service. The migration script, the support tool, the worker someone adds next quarter: none of them know the rule exists. Put the check on the data, inside the write that changes it, and there is no way around it. 03 One write, one truth. If a change and its consequences cannot commit together, you do not have a system. You have two systems and a race between them. Rollback has to mean everything rolls back. 04 Counters, queues, and buffers are state, not cache. They deserve the same transaction as the row next to them. Rebuilding them in a second store is how a balance and a rate limit end up disagreeing about the same second. 05 The network is the speed limit. Every round trip between your data and your logic is latency you paid for and correctness you gave up while waiting. The hot path should not have a network in it. 06 The application user is the database user. Every client authenticates to the database as itself, and policies decide, per user, what may be read and written. There is no shared service account and no privileged connection to hijack: a hostile query runs as the user, with the user's permissions, and can do nothing the user could not do anyway. Nothing to inject into, and no second copy of the rules in an API layer to drift. What ReifyDB is. ReifyDB is one database for that state. Tables hold the rows. Views hold the derived numbers, and the write keeps them current; there is nothing to refresh. Rules are procedures and handlers: code you version and test inside the database, running inside the transaction that changes the data. Not a trigger someone forgot. Counters, queues, ring buffers, and histograms are built in, transactional, and one query away. Embed it in your process or run it as a server. Either way, the hot path has no network in it. It also knows who is asking. Clients authenticate to the database as themselves, over WebSocket or HTTP, and policies gate every read and write per user. There is nothing in front of it holding the one password or re-checking permissions: clients talk to ReifyDB, and the rules about who may do what live with the data, like every other rule. Same feature, two stacks. Alice places an order. First on today's stack, then on ReifyDB. Today alice POST /orders api server may alice? build the query as "app", the one account postgres insert, debit redis drop cached balance queue worker: totals cron revenue, later alice polls balance, revenue: stale in between 5 systems runs as "app" stale With ReifyDB alice place_order(...) reifydb policy alice may place orders procedure check balance, insert, debit view revenue, updated by the same write one transaction alice sees balance, revenue: current, pushed 1 system runs as alice current Status Version 0.9. Not production ready. APIs and guarantees will change, and every page says so. What will not change is the list above. If you have written that cron job. If you have shipped a service whose entire job is knowing which key to delete. If you have ever explained to someone why the dashboard and the database disagree. Then you already agree with this page. Agree, and come build it. Disagree, and say so. One database instead of Postgres + Redis + a queue + a cron job. Challenge me with your opinion Read the Docs Star on GitHub ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/pitch/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started $ reifydb pitch slide 1 of 5 [full] +----------------------------------------------------------------------------------------------+ ReifyDB One database instead of Postgres + Redis + a queue + a cron job. +----------------------------------------------------------------------------------------------+ ← Prev Next → =============================================================================== URL: https://reifydb.com/playground/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Loading the playground... =============================================================================== URL: https://reifydb.com/support/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started Support Get help with ReifyDB through community channels or commercial support. Commercial Support Enterprise support and consulting for production deployments. Contact Me → GitHub Issues Report bugs, request features, or contribute to development. Open Issue → Book a Call Schedule time to discuss your use case or get technical guidance. Schedule Call → GitHub Discussions Ask questions, share ideas, and engage with the community. Discussions → Follow ReifyDB ReifyDB The database that runs your backend logic. Product Documentation Blog FAQ Resources Contact Support Book a Call Community GitHub X (Twitter) Discord © 2026 ReifyDB. All Rights Reserved. License: Apache-2.0 =============================================================================== URL: https://reifydb.com/tour/ =============================================================================== ReifyDB Developers Build Docs Guides, references, and API documentation Tour Interactive walkthrough of core features Playground Try ReifyDB queries in the browser Resources Learn Blog Engineering deep dives and product updates FAQ Frequently asked questions Support Get help from the team Company About Manifesto Why the Postgres + Redis + cron stack is a bug Mission Why we are building ReifyDB Values The principles that guide our work Contact Reach out to the team Get Started $ reifydb tour step 1 of 9 Welcome to the Tour This tour walks you through RQL interactively. Here's how to use the UI: Editor controls (top-right of each snippet): [[]] expand to fullscreen (Esc to exit) [cp] copy code to clipboard [↺] reset code to original Running a statement: Click [run] or press Ctrl+Enter / Cmd+Enter Navigation: ← Prev / Next → buttons at the bottom ← / → arrow keys (when not typing in the editor) Dot indicators to jump to any step directly Extra widgets (appear on some steps): [refresh] on the ASCII bar chart: re-queries the DB after running the snippet above Try Run on the snippet below, then press Next → to begin. tour: welcome from [ {step: 1, topic: "hello rql"}, {step: 2, topic: "querying tables"}, {step: 3, topic: "filtering rows"} ] ← Prev Next →