Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
9ea2d05
added query tracing and links
javier Dec 10, 2025
559d686
improved architecture guide. Adding multi URL to ILP docs
javier Dec 10, 2025
484a248
arrays and nanos
javier Dec 10, 2025
25e2a6e
byoc link
javier Dec 10, 2025
1f6f8ce
added reference to flyway
javier Dec 10, 2025
5668985
smaller images
javier Dec 10, 2025
ffcee5a
playbook initial draft
javier Dec 18, 2025
db4ace8
more drafts. Needs review
javier Dec 18, 2025
e4f327b
Merge branch 'main' into jv/playbook
javier Dec 18, 2025
cd5ad32
fixing broken links
javier Dec 18, 2025
c52ac49
draft pages. Might contain broken links and queries
javier Dec 18, 2025
99219b6
added trades table to schema info
javier Dec 18, 2025
6a13508
fixing broken links
javier Dec 18, 2025
0a58315
improved playbook content. Need to review queries mostly
javier Dec 18, 2025
bb1fbbc
fixing broken links
javier Dec 18, 2025
d0cb029
fixing links
javier Dec 18, 2025
2495dba
improved recipe
javier Dec 18, 2025
cf18db0
fixing link
javier Dec 18, 2025
a86a252
renamed files to match sidebar titles
javier Dec 19, 2025
fd2eae8
new playbook entries
javier Dec 19, 2025
c20e851
moved playbook inside guides and tutorials
javier Dec 19, 2025
4656c20
new label for playbook
javier Dec 19, 2025
7692abb
Merge main into jv/playbook, add Cookbook section
javier Jan 12, 2026
fcaad69
solved conflicts and links after docs revamp
javier Jan 12, 2026
80ddec8
renaming playbook to cookbook
javier Jan 12, 2026
4a13be6
Merge remote-tracking branch 'origin/main' into jv/playbook
javier Jan 12, 2026
30b4de5
changing the pivot cookbook recipe
javier Jan 12, 2026
52178b6
updated datasets page
javier Jan 12, 2026
3329140
changed link to cookbook overview
javier Jan 12, 2026
52a2248
improved query for compound interest
javier Jan 12, 2026
5eff2ab
improved queries for demo for financial recipes in cookbook
javier Jan 12, 2026
88375b7
improved queries
javier Jan 12, 2026
86f7cfb
improved recipe by using lag
javier Jan 12, 2026
09feb8b
improved queries
javier Jan 12, 2026
9d6fa5f
improved examples and revamped sidebar
javier Jan 13, 2026
f5cfe90
improved queries. Removed outdated section
javier Jan 13, 2026
0c8c5af
improved sql
javier Jan 13, 2026
a22f8f4
note formatting
javier Jan 13, 2026
9c07df2
improved formatting and examples
javier Jan 13, 2026
a8d8ac8
full revamp of this recipe
javier Jan 13, 2026
3fd2d4c
adding new recipe for local min and max
javier Jan 13, 2026
2b4af11
trimming recipe
javier Jan 13, 2026
d79c341
remove extra section
javier Jan 13, 2026
8eded5e
simplified queries and trimmed content
javier Jan 13, 2026
61db4e2
fixing histograms recipe
javier Jan 13, 2026
f6b92c0
removing extra fluff
javier Jan 13, 2026
1b3dd40
improved recipes
javier Jan 13, 2026
5dc103b
moved notes/info messages to the top
javier Jan 13, 2026
58932e8
making first level of cookbook not collapsed when opening the tutoria…
javier Jan 13, 2026
f245d9d
fixed markdown headers
javier Jan 13, 2026
3756e78
rephrasing
javier Jan 13, 2026
975c223
showing demo as .com
javier Jan 13, 2026
82065f6
fixing title case
javier Jan 13, 2026
8f9e742
vwap from OHLC
javier Jan 14, 2026
c335855
merging main and solving conflicts (title case to sentence case)
javier Jan 14, 2026
8dc856a
changing link to new target
javier Jan 14, 2026
9b9722b
removing USD references from demo
javier Jan 14, 2026
5fa9a3a
tick trin modified and adding aggressor volume imbalance
javier Jan 14, 2026
0f56937
adding results for nicer explanation
javier Jan 14, 2026
25c1af1
beter calculation for rolling stddev
javier Jan 14, 2026
e43bd31
simplifying schema
javier Jan 14, 2026
28b7ec8
more positive rewrite
javier Jan 14, 2026
7fa5d44
rephrasing for clarity
javier Jan 14, 2026
32f7c91
less negative view of missing features. Added extra explanation for f…
javier Jan 14, 2026
c1562d4
improved tick and trin recipe
javier Jan 15, 2026
ce2342e
clarified bollinger with a note
javier Jan 15, 2026
f3e31ab
adding note to stddev
javier Jan 15, 2026
8a4ee47
Adding views section and DECIMAL storage size
javier Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions documentation/cookbook/demo-data-schema.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Demo Data Schema
title: Demo data schema
sidebar_label: Demo data schema
description: Schema and structure of the FX market data and cryptocurrency trades available on demo.questdb.io
---
Expand All @@ -19,11 +19,11 @@ The demo instance provides two independent datasets:

---

## FX Market Data (Simulated)
## FX market data (simulated)

The FX dataset contains simulated foreign exchange market data for 30 currency pairs. We fetch real reference prices from Yahoo Finance every few seconds, but all order book levels and price updates are generated algorithmically based on these reference prices.

### core_price Table
### core_price table

The `core_price` table contains individual FX price updates from various liquidity providers. Each row represents a bid/ask quote update for a specific currency pair from a specific ECN.

Expand All @@ -32,16 +32,16 @@ The `core_price` table contains individual FX price updates from various liquidi
```sql title="core_price table structure"
CREATE TABLE 'core_price' (
timestamp TIMESTAMP,
symbol SYMBOL CAPACITY 16384 CACHE,
ecn SYMBOL CAPACITY 256 CACHE,
symbol SYMBOL,
ecn SYMBOL,
bid_price DOUBLE,
bid_volume LONG,
ask_price DOUBLE,
ask_volume LONG,
reason SYMBOL CAPACITY 256 CACHE,
reason SYMBOL,
indicator1 DOUBLE,
indicator2 DOUBLE
) timestamp(timestamp) PARTITION BY HOUR TTL 3 DAYS WAL;
) timestamp(timestamp) PARTITION BY HOUR TTL 3 DAYS;
```

#### Columns
Expand All @@ -58,7 +58,7 @@ CREATE TABLE 'core_price' (

The table tracks **30 currency pairs**: EURUSD, GBPUSD, USDJPY, USDCHF, AUDUSD, USDCAD, NZDUSD, EURJPY, GBPJPY, EURGBP, AUDJPY, CADJPY, NZDJPY, EURAUD, EURNZD, AUDNZD, GBPAUD, GBPNZD, AUDCAD, NZDCAD, EURCAD, EURCHF, GBPCHF, USDNOK, USDSEK, USDZAR, USDMXN, USDSGD, USDHKD, USDTRY.

#### Sample Data
#### Sample data

```questdb-sql demo title="Recent core_price updates"
SELECT * FROM core_price
Expand All @@ -81,7 +81,7 @@ LIMIT -10;
| 2025-12-18T11:46:13.066700Z | CADJPY | Currenex | 113.63 | 20300827 | 114.11 | 19720915 | normal | 0.55 | |
| 2025-12-18T11:46:13.071607Z | NZDJPY | Currenex | 89.95 | 35284228 | 90.46 | 30552528 | liquidity_event | 0.69 | |

### market_data Table
### market_data table

The `market_data` table contains order book snapshots for currency pairs. Each row represents a complete view of the order book at a specific timestamp, with bid and ask prices and volumes stored as 2D arrays.

Expand Down Expand Up @@ -109,7 +109,7 @@ The arrays are structured so that:
- `asks[1]` contains ask prices (ascending order - lowest first)
- `asks[2]` contains corresponding ask volumes

#### Sample Query
#### Sample query

```questdb-sql demo title="Recent order book snapshots"
SELECT timestamp, symbol,
Expand All @@ -132,7 +132,7 @@ LIMIT -5;

Each order book snapshot contains 40 bid levels and 40 ask levels.

### fx_trades Table
### fx_trades table

The `fx_trades` table contains simulated FX trade executions. Each row represents a trade that executed against the order book, with realistic partial fills and level walking.

Expand All @@ -150,7 +150,7 @@ CREATE TABLE 'fx_trades' (
quantity DOUBLE,
counterparty SYMBOL,
order_id UUID
) timestamp(timestamp) PARTITION BY HOUR TTL 1 MONTH WAL;
) timestamp(timestamp) PARTITION BY HOUR TTL 1 MONTH;
```

#### Columns
Expand All @@ -166,7 +166,7 @@ CREATE TABLE 'fx_trades' (
- **`counterparty`** - 20-character LEI (Legal Entity Identifier) of the counterparty
- **`order_id`** - Parent order identifier (multiple trades can share the same `order_id` for partial fills)

#### Sample Data
#### Sample data

```questdb-sql demo title="Recent FX trades"
SELECT * FROM fx_trades
Expand All @@ -189,48 +189,48 @@ LIMIT -10;
| 2026-01-12T12:18:57.509773474Z | GBPUSD | Currenex | ae6b771b-5abd-44c7-9e0e-3527ce6fb5b4 | sell | false | 1.3404 | 62305.0 | 006728CF215E44412D18 | 54ff8191-1891-4a5c-8b67-d5cd961ec5e8 |
| 2026-01-12T12:18:57.334732460Z | USDTRY | EBS | 469637a5-6553-4aad-aad9-f7114c8a442d | sell | true | 43.1 | 101177.0 | 002CAC92E93AB4B3D30C | 2ce77a03-0f21-4241-8ca7-903080848dc0 |

### FX Materialized Views
### FX materialized views

The FX dataset includes several materialized views providing pre-aggregated data at different time intervals:

#### Best Bid/Offer (BBO) Views
#### Best bid/offer (BBO) views

- **`bbo_1s`** - Best bid and offer aggregated every 1 second
- **`bbo_1m`** - Best bid and offer aggregated every 1 minute
- **`bbo_1h`** - Best bid and offer aggregated every 1 hour
- **`bbo_1d`** - Best bid and offer aggregated every 1 day

#### Core Price Aggregations
#### Core price aggregations

- **`core_price_1s`** - Core prices aggregated every 1 second
- **`core_price_1d`** - Core prices aggregated every 1 day

#### Market Data OHLC
#### Market data OHLC

- **`market_data_ohlc_1m`** - Open, High, Low, Close candlesticks at 1-minute intervals
- **`market_data_ohlc_15m`** - OHLC candlesticks at 15-minute intervals
- **`market_data_ohlc_1d`** - OHLC candlesticks at 1-day intervals

#### FX Trades OHLC
#### FX trades OHLC

- **`fx_trades_ohlc_1m`** - OHLC candlesticks from trade executions at 1-minute intervals
- **`fx_trades_ohlc_1h`** - OHLC candlesticks from trade executions at 1-hour intervals

These views are continuously updated and optimized for dashboard and analytics queries on FX data.

### FX Data Volume
### FX data volume

- **`market_data`**: Approximately **160 million rows** per day (order book snapshots)
- **`core_price`**: Approximately **73 million rows** per day (price updates across all ECNs and symbols)
- **`fx_trades`**: Approximately **5.1 million rows** per day (trade executions)

---

## Cryptocurrency Trades (Real)
## Cryptocurrency trades (real)

The cryptocurrency dataset contains **real market data** streamed live from the OKX exchange using FeedHandler. These are actual executed trades, not simulated data.

### trades Table
### trades table

The `trades` table contains real cryptocurrency trade data. Each row represents an actual executed trade for a cryptocurrency pair.

Expand All @@ -243,7 +243,7 @@ CREATE TABLE 'trades' (
price DOUBLE,
amount DOUBLE,
timestamp TIMESTAMP
) timestamp(timestamp) PARTITION BY DAY WAL;
) timestamp(timestamp) PARTITION BY DAY;
```

#### Columns
Expand All @@ -254,9 +254,9 @@ CREATE TABLE 'trades' (
- **`price`** - Execution price of the trade
- **`amount`** - Trade size (volume in base currency)

The table tracks **12 cryptocurrency pairs**: ADA-USDT, AVAX-USD, BTC-USDT, DAI-USD, DOT-USD, ETH-BTC, ETH-USDT, LTC-USD, SOL-BTC, SOL-USD, UNI-USD, XLM-USD.
The table tracks **12 cryptocurrency pairs**: ADA-USDT, AVAX-USDT, BTC-USDT, DAI-USDT, DOT-USDT, ETH-BTC, ETH-USDT, LTC-USDT, SOL-BTC, SOL-USDT, UNI-USDT, XLM-USDT.

#### Sample Data
#### Sample data

```questdb-sql demo title="Recent cryptocurrency trades"
SELECT * FROM trades
Expand All @@ -268,40 +268,40 @@ LIMIT -10;
| symbol | side | price | amount | timestamp |
| -------- | ---- | ------- | ---------- | --------------------------- |
| BTC-USDT | buy | 85721.6 | 0.00045714 | 2025-12-18T19:31:11.203000Z |
| BTC-USD | buy | 85721.6 | 0.00045714 | 2025-12-18T19:31:11.203000Z |
| BTC-USDT | buy | 85721.6 | 0.00045714 | 2025-12-18T19:31:11.203000Z |
| BTC-USDT | buy | 85726.6 | 0.00001501 | 2025-12-18T19:31:11.206000Z |
| BTC-USD | buy | 85726.6 | 0.00001501 | 2025-12-18T19:31:11.206000Z |
| BTC-USDT | buy | 85726.6 | 0.00001501 | 2025-12-18T19:31:11.206000Z |
| BTC-USDT | buy | 85726.9 | 0.000887 | 2025-12-18T19:31:11.206000Z |
| BTC-USDT | buy | 85726.9 | 0.000887 | 2025-12-18T19:31:11.206000Z |
| BTC-USD | buy | 85726.9 | 0.000887 | 2025-12-18T19:31:11.206000Z |
| BTC-USDT | buy | 85731.3 | 0.00004393 | 2025-12-18T19:31:11.206000Z |
| BTC-USD | buy | 85731.3 | 0.00004393 | 2025-12-18T19:31:11.206000Z |
| BTC-USDT | buy | 85731.3 | 0.00004393 | 2025-12-18T19:31:11.206000Z |
| ETH-USDT | sell | 2827.54 | 0.006929 | 2025-12-18T19:31:11.595000Z |
| ETH-USDT | sell | 2827.54 | 0.006929 | 2025-12-18T19:31:11.595000Z |
| ETH-USD | sell | 2827.54 | 0.006929 | 2025-12-18T19:31:11.595000Z |

### Cryptocurrency Materialized Views
### Cryptocurrency materialized views

The cryptocurrency dataset includes materialized views for aggregated trade data:

#### Trades Aggregations
#### Trades aggregations

- **`trades_latest_1d`** - Latest trade data aggregated daily
- **`trades_OHLC_15m`** - OHLC candlesticks for cryptocurrency trades at 15-minute intervals

These views are continuously updated and provide faster query performance for cryptocurrency trade analysis.

### Cryptocurrency Data Volume
### Cryptocurrency data volume

- **`trades`**: Approximately **3.7 million rows** per day (real cryptocurrency trades)

---

## Data Retention
## Data retention

**FX tables** (`core_price` and `market_data`) use a **3-day TTL (Time To Live)**, meaning data older than 3 days is automatically removed. This keeps the demo instance responsive while providing sufficient recent data.

**Cryptocurrency trades table** has **no retention policy** and contains historical data dating back to **March 8, 2022**. This provides over 3 years of real cryptocurrency trade history for long-term analysis and backtesting.

## Using the Demo Data
## Using the demo data

You can run queries against both datasets directly on [demo.questdb.com](https://demo.questdb.io). Throughout the Cookbook, recipes using demo data will include a direct link to execute the query.

Expand Down
8 changes: 4 additions & 4 deletions documentation/cookbook/index.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
title: Cookbook Overview
title: Cookbook overview
sidebar_label: Overview
description: Quick recipes and practical examples for common QuestDB tasks and queries
---

The Cookbook is a collection of **short, actionable recipes** that demonstrate how to accomplish specific tasks with QuestDB. Each recipe follows a problem-solution-result format, making it easy to find and apply solutions quickly.

## What is the Cookbook?
## What is the cookbook?

Unlike comprehensive reference documentation, the Cookbook focuses on practical examples for:

Expand All @@ -24,15 +24,15 @@ The Cookbook is organized into three main sections:
- **Programmatic** - Language-specific client examples and integration patterns
- **Operations** - Deployment, configuration, and operational tasks

## Running the Examples
## Running the examples

**Most recipes run directly on our [live demo instance at demo.questdb.com](https://demo.questdb.com)** without any local setup. Queries that can be executed on the demo site are marked with a direct link to run them.

For recipes that require write operations or specific configuration, the recipe will indicate what setup is needed.

The demo instance contains live FX market data with tables for core prices and order book snapshots. See the [Demo Data Schema](/docs/cookbook/demo-data-schema/) page for details about available tables and their structure.

## Using the Cookbook
## Using the cookbook

Each recipe follows a consistent format:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
---
title: Query Multiple Tables Dynamically in Grafana
title: Query multiple tables dynamically in Grafana
sidebar_label: Dynamic table queries
description: Use Grafana variables to dynamically query multiple tables with the same schema for time-series visualization
---

Query multiple QuestDB tables dynamically in Grafana using dashboard variables. This is useful when you have many tables with identical schemas (e.g., sensor data, metrics from different sources) and want to visualize them together without hardcoding table names in your queries.

## Problem: Visualize Many Similar Tables
## Problem: Visualize many similar tables

You have 100+ tables with the same structure (e.g., `sensor_1`, `sensor_2`, ..., `sensor_n`) and want to:
1. Display data from all tables on a single Grafana chart
2. Avoid manually updating queries when tables are added or removed
3. Allow users to select which tables to visualize via dashboard controls

## Solution: Use Grafana Variables with Dynamic SQL
## Solution: Use Grafana variables with dynamic SQL

Create Grafana dashboard variables that query QuestDB for table names, then use string aggregation functions to build the SQL query dynamically.

### Step 1: Get Table Names
### Step 1: Get table names

First, query QuestDB to get all relevant table names:

Expand All @@ -28,7 +28,7 @@ WHERE table_name LIKE 'sensor_%';

This returns a list of all tables matching the pattern.

### Step 2: Create Grafana Variables
### Step 2: Create Grafana variables

Create two dashboard variables to construct the dynamic query:

Expand Down Expand Up @@ -59,7 +59,7 @@ WHERE table_name LIKE 'sensor_%';

This creates the column selection list with aggregation functions.

### Step 3: Use Variables in Dashboard Query
### Step 3: Use variables in dashboard query

Now reference these variables in your Grafana chart query:

Expand All @@ -77,7 +77,7 @@ FROM sensor_1 ASOF JOIN sensor_2 ASOF JOIN sensor_3 ASOF JOIN sensor_4
SAMPLE BY 1s FROM cast(1571176800000000 as timestamp) TO cast(1571349600000000 as timestamp) FILL(PREV);
```

## How It Works
## How it works

The solution uses three key QuestDB features:

Expand All @@ -99,7 +99,7 @@ Combined with Grafana's variable interpolation:

This ensures that even if tables update at different rates, you get a complete dataset with the most recent known value from each table.

## Adapting the Pattern
## Adapting the pattern

**Filter by different patterns:**
```sql
Expand All @@ -114,7 +114,7 @@ WHERE table_name LIKE 'sensor_%'
AND table_name NOT IN ('sensor_test', 'sensor_backup')
```

## Programmatic Alternative
## Programmatic alternative

If you're not using Grafana, you can achieve the same result programmatically:

Expand Down Expand Up @@ -142,7 +142,7 @@ If you're not using Grafana, you can achieve the same result programmatically:
"""
```

## Handling Different Sampling Intervals
## Handling different sampling intervals

When tables have different update frequencies, use FILL to handle gaps:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Overlay Two Time Series with Time Shift
title: Overlay two time series with time shift
sidebar_label: Overlay with timeshift
description: Overlay yesterday's and today's data on the same Grafana chart using time shift
---
Expand Down
8 changes: 4 additions & 4 deletions documentation/cookbook/integrations/grafana/read-only-user.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Configure Read-Only User for Grafana
title: Configure read-only user for Grafana
sidebar_label: Read-only user
description: Set up a read-only PostgreSQL user for Grafana dashboards while maintaining admin access for DDL operations
---
Expand All @@ -10,7 +10,7 @@ Configure a dedicated read-only user for Grafana to improve security by preventi
For QuestDB Enterprise, use the comprehensive [Role-Based Access Control (RBAC)](/docs/security/rbac/) system to create granular user permissions and roles. The configuration below applies to QuestDB Open Source.
:::

## Problem: Separate Read and Write Access
## Problem: Separate read and write access

You want to:
1. Connect Grafana with read-only credentials
Expand All @@ -19,7 +19,7 @@ You want to:

However, QuestDB's PostgreSQL wire protocol doesn't support standard PostgreSQL user management commands like `CREATE USER` or `GRANT`.

## Solution: Enable the Read-Only User
## Solution: Enable the read-only user

QuestDB Open Source supports a built-in read-only user that can be enabled via configuration. This gives you two users:
- **Admin user** (default: `admin`): Full access for DDL and DML operations
Expand Down Expand Up @@ -58,7 +58,7 @@ docker run \
questdb/questdb:latest
```

### Using the Read-Only User
### Using the read-only user

After enabling, you have two separate users:

Expand Down
Loading