Skip to main content

Overview

This template provides a production‑ready QuestDB instance as a Monk runnable. You can:
  • Run it directly to get a managed high-performance time-series database with sensible defaults
  • Inherit it in your own runnable to seamlessly add time-series data storage to your stack
It exposes QuestDB’s web console and API on port 9000, PostgreSQL wire protocol on port 8812, InfluxDB line protocol on port 9009, and persists data to a host volume. QuestDB is an open-source database designed for high-throughput ingestion and fast SQL queries with microsecond-level performance.

What this template manages

  • QuestDB container (questdb/questdb image, configurable tag)
  • Network services on ports 9000 (HTTP/Web Console), 8812 (PostgreSQL), 9009 (InfluxDB)
  • Persistent volumes for database and configuration
  • HTTP API and interactive web console
  • PostgreSQL wire protocol support
  • InfluxDB line protocol for high-speed ingestion

Quick start (run directly)

  1. Load templates
monk load MANIFEST
  1. Run QuestDB with defaults
monk run questdb/questdb
  1. Access the services
Once started, connect to:
  • Web Console: http://localhost:9000
  • HTTP API: http://localhost:9000
  • PostgreSQL wire: localhost:8812
  • InfluxDB line protocol: localhost:9009

Configuration

Key variables you can customize in this template:
variables:
  questdb-image-tag: "latest"         # container image tag
  http-port: "9000"                   # HTTP and web console port
  pg-port: "8812"                     # PostgreSQL wire protocol port
  influxdb-port: "9009"               # InfluxDB line protocol port
  cairo-commit-lag: "1000"            # commit lag in milliseconds (env: QDB_CAIRO_COMMIT_LAG)
  shared-worker-count: "2"            # shared worker threads (env: QDB_SHARED_WORKER_COUNT)
Data is persisted under ${monk-volume-path}/questdb on the host. Configuration files are mounted from files/ directory. Inherit the QuestDB runnable in your application and declare a connection. Example:
namespace: myapp
timeseries-db:
  defines: runnable
  inherits: questdb/questdb
iot-collector:
  defines: runnable
  containers:
    collector:
      image: myorg/iot-collector
  connections:
    tsdb:
      runnable: timeseries-db
      service: questdb
  variables:
    questdb-host:
      value: <- connection-hostname("tsdb")
    questdb-http-port:
      value: "9000"
    questdb-ilp-port:
      value: "9009"
Then run your app:
monk run myapp/iot-collector

Ports and connectivity

  • Service: questdb on TCP ports 9000 (HTTP), 8812 (PostgreSQL), 9009 (InfluxDB)
  • From other runnables in the same process group, use connection-hostname("\<connection-name>") to resolve the QuestDB host.

Persistence and configuration

  • Data path: ${monk-volume-path}/questdb/db:/root/.questdb/db
  • Config path: files/server.conf and files/log.conf mounted into the container
  • All tables and partitions are persisted to the data volume

Features

  • High Performance: Millions of rows per second ingestion
  • SQL Support: Full SQL with time-series extensions
  • Multiple Protocols: PostgreSQL wire, InfluxDB line protocol, HTTP
  • Real-Time: Query data as it arrives
  • Efficient Storage: Column-oriented, time-partitioned
  • Built-In Functions: Time-series aggregations and window functions
  • Web Console: Interactive SQL editor and visualization
  • PostgreSQL Compatible: Use standard PostgreSQL clients

SQL Examples

Create time-series table:
CREATE TABLE sensor_data (
    ts TIMESTAMP,
    sensor_id SYMBOL,
    temperature DOUBLE,
    humidity DOUBLE
) TIMESTAMP(ts) PARTITION BY DAY;
Insert data:
INSERT INTO sensor_data VALUES
    ('2024-01-01T10:00:00.000000Z', 'sensor-1', 22.5, 45.0),
    ('2024-01-01T10:01:00.000000Z', 'sensor-1', 22.7, 46.0);
Time-series query:
SELECT ts, sensor_id, avg(temperature)
FROM sensor_data
WHERE ts > dateadd('d', -7, now())
SAMPLE BY 1h;

InfluxDB Line Protocol

Send data via ILP (fastest ingestion method):
# TCP
echo "sensor,location=room1 temperature=22.5,humidity=45.0" | \
  nc localhost 9009

# UDP (even faster, requires configuration)
echo "sensor,location=room1 temperature=22.5,humidity=45.0" | \
  nc -u localhost 9009
Python example:
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 9009))
sock.sendall(b'sensor,location=room1 temperature=22.5,humidity=45.0\n')
sock.close()

PostgreSQL Client Access

Use any PostgreSQL client:
psql -h localhost -p 8812 -U admin -d qdb
Python with psycopg2:
import psycopg2

conn = psycopg2.connect(
    host='localhost',
    port=8812,
    user='admin',
    password='quest',
    database='qdb'
)

cur = conn.cursor()
cur.execute("SELECT * FROM sensor_data LIMIT 10")
print(cur.fetchall())

Use cases

QuestDB excels at:
  • IoT sensor data collection
  • Application metrics and monitoring
  • Financial market data
  • Real-time analytics
  • Event logging
  • Network monitoring
  • Industrial telemetry
  • Use pgadmin/ for web-based database administration
  • Combine with grafana/ for time-series visualization
  • Integrate with telegraf/ for metrics collection

Troubleshooting

  • Access Web Console at http://localhost:9000 to run SQL queries interactively
  • Check server status with curl http://localhost:9000/status
  • Check logs:
monk logs -l 500 -f questdb/questdb
  • For ingestion issues, verify InfluxDB line protocol port (9009) is accessible
  • For query performance, ensure proper indexing on SYMBOL columns and use SAMPLE BY for time-series aggregations
  • Monitor disk space for time-partitioned tables
  • Ensure the host volumes are writable by the container user