Open-source project
readysettech/readyset avatar
readysettech/readyset

Readyset: a wire-compatible SQL cache that tracks your replication stream

Readyset is a MySQL and Postgres wire-compatible caching layer that sits in front of existing databases to speed up queries and horizontally scale read throughput. Under the hood, ReadySet caches the results of cached select statements and incrementally updates these results over time as the underlying data changes.

5,285 stars168 forksRustNOASSERTION

At a glance

What is it?
Readyset sits between an application and Postgres or MySQL and answers cached SELECTs from memory, keeping results current by consuming the database replication stream. It is for teams whose read traffic has outgrown a single primary but who cannot rewrite queries or manage invalidation by hand.
Who is it for?
Adopt Readyset when your read-heavy workload is already expressed as SQL and you can point a replication stream at it, because that is the only path by which it learns about writes. Skip it if you need cached queries to survive a database failover without verification, or if your workload is mostly writes.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Readyset targets: read scaling without a rewrite

The usual answer to read pressure is a cache in front of the database, and the usual cost is invalidation. You write keys, you set TTLs, you either serve stale rows for a while or you build a write path that clears entries at the right moment. Readyset takes the other route. It is described in the README as a transparent database cache for Postgres and MySQL that gives the performance of an in-memory key-value store without requiring that you rewrite your app or manually handle cache invalidation. The audience is teams already running Postgres or MySQL who want horizontal read throughput but do not want to change application code or introduce a separate data model. Wire compatibility is the load-bearing part of that promise: the README states it can be used along with your current ORM or database client, so the change is a connection target rather than a code change. That is a narrower claim than "drop-in replacement for your database", and it is worth reading it that way. Readyset caches the results of SELECT statements; it is not a write-scaling layer, and it is not a general-purpose proxy.

How Readyset keeps cached query results current

The mechanism is replication-based rather than TTL-based. According to the README, Readyset keeps cached query results in sync with your database automatically by utilizing your database's replication stream, and it incrementally updates those results over time as the underlying data changes. So the data flow has two directions. On the client side, a query arrives over the Postgres or MySQL wire protocol; if it matches a cached statement, Readyset answers from memory instead of forwarding it. On the database side, Readyset consumes the replication stream and applies the changes to the cached results, which is why no manual invalidation step appears in the workflow. The repository layout is consistent with that design: there are separate crates for the two wire protocols (psql-srv, mysql-srv), an adapter layer (readyset-adapter), a dataflow layer (readyset-dataflow), and a set of smaller structures such as merging-interval-tree and partial-map that look like the incremental-update machinery. The practical consequence is that the cache is only as current as the replication stream feeding it, and only as useful as the set of queries it has been told to cache. The README does not document how it decides which queries to cache, so treat that as something to check in the docs rather than assume.

Installing Readyset and caching your first query

The README gives a one-line quickstart intended to take five minutes or less. It downloads and runs a script; you should read it before piping it to a shell, which is true of every curl-to-bash installer and not a criticism specific to this project.

bash
bash -c "$(curl -sSL https://launch.readyset.io)"

The README also lists two other install paths, a Docker image and a Linux binary, both linked from the getting started guide at readyset.io/docs/cache/install-rs. If you want to try Readyset against a local database first, the repository ships a docker-compose.yml that starts both engines with the credentials the quickstart expects.

bash
docker compose up -d

That file defines a mysql service on port 3306 with MYSQL_ROOT_PASSWORD=readyset and MYSQL_DATABASE=testdb, and a postgres service on port 5432 with POSTGRES_PASSWORD=readyset and POSTGRES_DB=testdb. Note the Postgres service command line: it starts postgres with -c wal_level=logical. That is the setting Readyset needs in order to read the replication stream, and it is the first thing to check on a database you did not start yourself.

The quickstart directory contains the rest of the demo material: compose.postgres.yml and compose.mysql.yml for each engine separately, imdb-postgres.sql and imdb-mysql.sql to load a sample dataset, check_db_postgres.sh and check_db_size.sh to inspect the database, readyset_demo.sh to drive the demo, and metrics.py with requirements.txt for reading metrics. The README does not spell out the arguments to those scripts, so open them before running them. After Readyset is running, the intended first use is to point your existing client at it instead of at the database and run the same SELECTs you already run. What you should see is the same result set, returned faster once the query is cached.

Where Readyset is the wrong tool

The clearest limitation is the one implied by the architecture: everything Readyset knows about your data arrives through the replication stream. If that stream stops, is misconfigured, or is not available at all, the cache has no way to stay current, and the README does not document a fallback mode, a staleness bound, or a rollback procedure for that situation. The README does not document rollback at all. That matters operationally, because a cache that is behind is worse than no cache if the application cannot tell the difference.

The second limitation is workload shape. Readyset caches the results of cached select statements, so a write-heavy service gets little from it, and a service whose reads are mostly single-row primary-key lookups may already be well served by an ordinary key-value cache with far less machinery. Readyset's advantage shows up with complex SQL reads, which is exactly the case where hand-written caching is painful.

The third is query support. The README does not state which SQL constructs can be cached and which cannot. Any adoption plan that assumes "all my reads" is making an assumption the README does not support; you have to check your actual query set against the documentation before trusting the number.

Readyset compared with a hand-rolled cache in front of the database

The obvious alternative is the one most teams already have: an application-level cache such as Redis or Memcached, with the application responsible for populating entries and invalidating them on write. The difference is not speed, it is where the invalidation logic lives. With an application cache, the correctness argument is yours to make and yours to maintain; every new write path is a chance to forget an invalidation. With Readyset, the correctness argument moves to the replication stream, and the failure mode changes from silent staleness in one code path to a dependency on replication being healthy. Neither is free. The application cache can serve any data shape you can serialize; Readyset only serves results of SQL it can cache, and it must be wire-compatible with your client, which it claims to be but which you should confirm against your ORM. A second alternative worth naming is a read replica: it scales reads with no caching semantics at all, but it does not reduce the cost of a complex query, only spreads it across more machines. Readyset's claim is that it turns complex SQL reads into lookups, which is a different lever.

Maintenance, releases and the BSL licence

The repository is not archived, and its most recent push was on 2026-09-22. Recent releases follow a dated naming scheme: stable-260827 published on 2026-08-27, stable-260730 on 2026-07-31, and stable-260720 on 2026-07-21. Roughly monthly stable tags give you a predictable upgrade cadence, though the release notes are not included here, so what changes between them is not something this article can tell you.

Upgrade cost is mostly about the cached query set. Cargo.toml shows the project patching several upstream crates to its own forks, including moka on a cost-aware-lfu branch and the rust-postgres family at a readyset-tagged revision. That is normal for a project this deep in the query path, but it means the dependency graph is not the plain crates.io one, which matters if you build from source rather than using the binary or image.

On licensing: the README states Readyset is licensed under BSL 1.1, converting to Apache 2.0 after four years, and that it is free to use on any number of nodes. The repository's LICENSE file is the authoritative text; the GitHub metadata for this repository reports the licence as NOASSERTION, so read the file rather than the badge. BSL is source-available rather than OSI-approved open source for the covered period, and whether that is acceptable depends on your organisation's policy. This is a description of the terms, not legal advice.

Editorial conclusion

Adopt Readyset when your read-heavy workload is already expressed as SQL and you can point a replication stream at it, because that is the only path by which it learns about writes. Skip it if you need cached queries to survive a database failover without verification, or if your workload is mostly writes. Before rollout, confirm three things in your own environment: that your database has logical replication enabled (the project's docker-compose.yml sets wal_level=logical for Postgres), that the queries you care about are actually supported by the cache, and that your client tolerates the connection string change. The quickstart script at launch.readyset.io is the fastest way to see the second and third answers for yourself.

Frequently asked questions

Is Readyset a caching server?

Yes. The README describes Readyset as a transparent database cache for Postgres and MySQL that sits between your application and database, caches the results of SELECT statements, and updates those results incrementally as the underlying data changes.

What are Readyset's main features?

Wire compatibility with Postgres and MySQL so existing ORMs and clients work unchanged, automatic cache maintenance from the database replication stream instead of manual invalidation, and incremental updates to cached query results. The README also points to a managed Readyset Cloud service.

What is Readyset?

Readyset is a caching layer for Postgres and MySQL written in Rust. It answers cached SELECTs from memory and keeps those results current by consuming your database's replication stream, so you do not rewrite your application or handle invalidation yourself.

Official sources

  1. Issues
  2. Project website
  3. README
  4. readysettech/readyset on GitHub
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/readysettech-readyset.svg)](https://hysenlabs.com/projects/readysettech-readyset)