PostgreSQL is one of the most potent relational databases, but performance can become a bottleneck as queries become complex. One of the most effective ways to reduce query latency without modifying application logic is caching, and Readyset provides a seamless solution. Readyset sits between your application and PostgreSQL, automatically caching queries and speeding up their response times considerably. In this guide, we’ll walk through: Installing Readyset on Ubuntu 24.04 using a .deb packa

Wagner Bianchi
2025-03-10 · 6 min read
PostgreSQL is one of the most potent relational databases, but performance can become a bottleneck as queries become complex. One of the most effective ways to reduce query latency without modifying application logic is caching, and Readyset provides a seamless solution.
Readyset sits between your application and PostgreSQL, automatically caching queries and speeding up their response times considerably.
In this guide, we’ll walk through:
Installing Readyset on Ubuntu 24.04 using a .deb package;
Configuring Readyset to connect to your upstream PostgreSQL database;
Running queries and caching results using the Northwind sample database;
Managing cached queries to optimize performance.
The Northwind PostgreSQL Sample Database can be downloaded and imported as below:
#: download the database dump and restore it
wget https://raw.githubusercontent.com/pthom/northwind_psql/master/northwind.sql
psql -U <dbuser> -W -h <db IP or DNS> -d template1 -c "create database northwind"
psql -U <dbuser> -W -h <db IP or DNS> -d northwind -f northwind.sql
You need to pay attention to security. We recommend creating a GROUP and a USER with the relevant configurations and permissions before you connect Readyset to your databases, which we call upstream databases. On the upstream database, you need to configure the wal_level as logical so Readyset can snapshot the database you have queries for caching and set up a logical replication to keep caching up-to-date.
Some other considerations for configuring your PostgreSQL with Readyset are at https://readyset.io/docs/reference/configure-your-database/postgres/generic-db-directions
Step 1: Prerequisites
Before setting up Readyset, ensure that a PostgreSQL database is already running. Readyset requires access to the database to snapshot the schema and cache queries.
Key Recommendations
Readyset should be installed on a different host than the PostgreSQL database to avoid resource contention.
The database server must allow Readyset to connect remotely.
For this tutorial, we assume:
Step 2: Installing Readyset on Ubuntu 24.04
2.1 Download the Readyset .deb Package
$ wget https://github.com/readysettech/readyset/releases/download/stable-250123/readyset_1.11.0-1_amd64.deb
2.2 Install Readyset Using dpk
$ dpkg -i readyset_1.11.0-1_amd64.deb
After installation, you should see:
Selecting previously unselected package readyset.
(Reading database ... 168043 files and directories currently installed.)
Preparing to unpack readyset_1.11.0-1_amd64.deb ...
Unpacking readyset (1.11.0-1) ...
Setting up readyset (1.11.0-1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/readyset.service → /usr/lib/systemd/system/readyset.service.
You also need to install the psql on the Readyset host:
$ apt install -y postgresql-client-common postgresql-client
To make sure Readyset will be able to connect to the upstream database host, give it a try:
$ pg_isready -d northwind -h 10.0.0.11 -p 5432 -U readyset
10.0.0.11:5432 - accepting connections
Step 3: Configuring Readyset
Before starting Readyset, configure it in /etc/readyset/readyset.conf.
3.1 Open the Configuration File
vim /etc/readyset/readyset.conf
3.2 Set the Database Connection
UPSTREAM_DB_URL="postgres://readyset:<pass>@10.0.0.11:5432/northwind"
LISTEN_ADDRESS="0.0.0.0:5433"
3.3 Start the Readyset Service
$ systemctl start readyset.service
To check if it’s running:
$ systemctl status readyset.service
If you want to check logs:
$ tail -n100 /var/lib/readyset/
…
2025-03-04T19:07:22.948022Z INFO replicators::noria_adapter: Snapshot finished
2025-03-04T19:07:22.988330Z INFO replicators::postgres_connector::connector: confirmed_flush_lsn="0/1B8DF80" wal_status="reserved"
2025-03-04T19:07:23.004533Z INFO replicators::noria_adapter: Streaming replication started
Step 4: Connecting to Readyset
Once Readyset is running, connect using the PostgreSQL client:
psql -U readyset -h 10.0.12 -W -p 5433 -d northwind
For more convenience when running queries, I will disable the “pager less” for returning result sets and enable the timing for the Readyset psql PostgreSQL client.
$ echo "\pset pager off" >> ~/.psqlrc
$ echo "\timing" >> ~/.psqlrc
Since Readyset acts as a proxy, queries sent here will be ready to be cached.
Step 5: Running Your First Cached Query
Run a real-world query using PostgreSQL’s Northwind database:
northwind=> SELECT order_id
, order_date
, shipped_date
, company_name
, contact_name
FROM orders t1 JOIN customers t2 ON t1.customer_id = t2.customer_id
JOIN employees t3 ON t1.employee_id = t3.employee_id
WHERE t1.ship_country='Brazil';
order_id | order_date | shipped_date | company_name | contact_name
----------+------------+--------------+------------------------+-------------------
10250 | 1996-07-08 | 1996-07-12 | Hanari Carnes | Mario Pontes
10253 | 1996-07-10 | 1996-07-16 | Hanari Carnes | Mario Pontes
...
11059 | 1998-04-29 | | Ricardo Adocicados | Janete Limeira
11068 | 1998-05-04 | | Queen Cozinha | Lúcia Carvalho
(83 rows)
Time: 54.390 ms
Since this is the first run, PostgreSQL processes it as usual. The time is ~54 ms.
We can use the EXPLAIN LAST STATEMENT Readyset command to see where this query was executed:
northwind=> EXPLAIN LAST STATEMENT;
Query_destination | Readyset_error
-------------------+----------------
upstream | ok
(1 row)
As expected, the query was proxied to the upstream database.
Step 6: Checking Proxied Queries
To check if Readyset intercepted the query:
SHOW PROXIED QUERIES;
Expected output:
northwind=> SHOW PROXIED QUERIES;
query id | proxied query | readyset supported | count
--------------------+-------------------------------------------------------------------------+--------------------+-------
q_33cfda0e3ac49afc | SELECT +| yes | 0
| "order_id", +| |
| "order_date", +| |
| "shipped_date", +| |
| "company_name", +| |
| "contact_name" +| |
| FROM +| |
| "orders" AS "t1" +| |
| JOIN "customers" AS "t2" ON ("t1"."customer_id" = "t2"."customer_id")+| |
| JOIN "employees" AS "t3" ON ("t1"."employee_id" = "t3"."employee_id")+| |
| WHERE +| |
| ("t1"."ship_country" = $1) | |
Time: 0.858 ms
The query is “readyset supported”, as seen on the above output.
Step 7: Creating a Cache for the Query
To explicitly cache this query:
northwind=> CREATE CACHE ALWAYS FROM q_33cfda0e3ac49afc;
Time: 923.076 ms
Step 8: Verifying the Cache
Check if the query is cached:
northwind=> SHOW CACHES;
query id | cache name | query text | fallback behavior | count
--------------------+--------------------+--------------------------------------------------------------------------+-------------------+-------
q_33cfda0e3ac49afc | q_33cfda0e3ac49afc | SELECT +| no fallback | 0
| | "public"."orders"."order_id", +| |
| | "public"."orders"."order_date", +| |
| | "public"."orders"."shipped_date", +| |
| | "public"."customers"."company_name", +| |
| | "public"."customers"."contact_name" +| |
| | FROM +| |
| | "public"."orders" +| |
| | JOIN "public"."customers" ON ( +| |
| | "public"."orders"."customer_id" = "public"."customers"."customer_id"+| |
| | ) +| |
| | JOIN "public"."employees" ON ( +| |
| | "public"."orders"."employee_id" = "public"."employees"."employee_id"+| |
| | ) +| |
| | WHERE +| |
| | ("public"."orders"."ship_country" = $1) | |
(1 row)
Time: 2.332 ms
At this point, Readyset is caching this query!
Step 9: Running the Cached Query
Rerun the query:
northwind=> SELECT order_id
, order_date
, shipped_date
, company_name
, contact_name
FROM orders t1 JOIN customers t2 ON t1.customer_id = t2.customer_id
JOIN employees t3 ON t1.employee_id = t3.employee_id
WHERE t1.ship_country='Brazil';
order_id | order_date | shipped_date | company_name | contact_name
----------+------------+--------------+------------------------+-------------------
10250 | 1996-07-08 | 1996-07-12 | Hanari Carnes | Mario Pontes
10253 | 1996-07-10 | 1996-07-16 | Hanari Carnes | Mario Pontes
…
11059 | 1998-04-29 | | Ricardo Adocicados | Janete Limeira
11068 | 1998-05-04 | | Queen Cozinha | Lúcia Carvalho
(83 rows)
Time: 1.232 ms
The same query execution, now using the Readyset cache took ~1 ms.
If we again EXPLAIN LAST STATEMENT:
northwind=> EXPLAIN LAST STATEMENT;
Query_destination | Readyset_error
-------------------+----------------
readyset | ok
(1 row)
🚀 The query execution time dropped more than 50 times! Readyset serves the result from the created cache, avoiding a full database load.
Step 10: Removing a Cached Query
To remove the cache, run:
northwind=> DROP CACHE q_33cfda0e3ac49afc;
DELETE 1
Time: 16.189 ms
Verify that it's gone:
SHOW CACHES;
With Readyset, you can significantly improve PostgreSQL query performance without modifying application code.
Using Readyset improves efficiency and performance orders of magnitude;
Queries are cached reducing upstream PostgreSQL load;
With this strategy you don't need to add more replicas or hardware;
Create custom caches for the queries you want fully optimized;
Using SHOW CACHES helps track performance improvements;
The EXPLAIN LAST STATEMENT shows you where the last statement was executed;
You don’t need any code changes, you can start with readyset now.
Play with our Cloud Demo: https://readyset.cloud/
Our Slack: https://go.readyset.io/community
Our Github: https://github.com/readysettech/readyset
Modern applications demand instant performance, even under unpredictable load. Readyset helps you eliminate slow queries, stabilize latency, and scale confidently.
Revolutionize your database performance with Readyset
Serve requests at sub-millisecond latencies with the modern database scaling and query caching system for MySQL and PostgreSQL.
Join our newsletter
Stay updated with the latest news, insights, and developments from Readyset — straight to your inbox.