Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Q in the Wild: Breaking Out of the Silo

Q is a strange language to love. Its syntax looks like someone bet a Lisp programmer they couldn’t make a language with fewer vowels. Its documentation assumes a specific kind of patience. And yet — once it clicks — you find yourself genuinely irritated when you have to do time-series work in anything else.

The problem is that Q exists in a silo. Not because it has to, but because the path of least resistance in a kdb+ shop is to write everything in Q. Tick infrastructure in Q. Analytics in Q. The internal tooling script that one person wrote in 2011 that nobody touches? Q. The REST endpoint that technically works but falls over if you look at it wrong? Wrapped Q.

This book is about breaking out of that pattern — not by replacing Q, but by making it a first-class participant in a modern polyglot stack.

The Silo Problem, Concretely

Here’s what a typical kdb+ shop looks like in practice:

[Feed Handler (C/Q)] → [Tickerplant (Q)] → [RDB (Q)] → [HDB (Q)]
                                                              ↑
                                                     [Analytics (Q)]
                                                              ↑
                                                    [Reports (Q? Excel?)]

Everything in that diagram is either Q or Excel. The Excel is because someone gave up on Q GUIs and the quants had to get their data somehow. The integration surface is basically non-existent.

Now here’s what a modern stack looks like when Q is doing what it’s good at and letting other tools do what they’re good at:

[Feed Handler] → [Kafka] → [kdb+ Feed Handler] → [Tickerplant (Q)]
                                                          |
                    ┌─────────────────────────────────────┘
                    ↓
              [RDB (Q)] ←→ [HDB (Q)]
                    |
         ┌──────────┴──────────────────────┐
         ↓                                 ↓
  [FastAPI gateway]              [pykx (Python analytics)]
         |                                 |
    [REST clients]              [Jupyter / ML pipelines]
    [Web dashboards]            [R research notebooks]
    [Compliance systems]        [Spark / dbt pipelines]

Q is still doing what it does best: ingesting, storing, and querying time-series data at speed. But now it’s connected. The Python team doesn’t need a Q license to get trade data. The compliance system doesn’t need to speak IPC. The dashboard doesn’t need to run inside a Q process.

What This Book Covers

Language bridges — Python (via pykx and qPython), Rust (via FFI and IPC), and R (via rkdb). Real patterns for passing typed data across language boundaries without your timestamps becoming floats or your symbols becoming bytes. Each chapter compares the available libraries honestly and tells you which one to use.

APIs and protocols — Q’s IPC protocol in depth, REST API wrappers, and how to build something external consumers can actually call without needing a Q license or understanding what hopen means.

Streaming — Kafka integration, WebSocket servers, and the patterns that let Q participate in real-time data pipelines as both producer and consumer, not just as the thing at the end of the pipe.

Tooling — IDEs that won’t make you feel like a hermit, linters, formatters, and the state of Q developer experience in 2026 (better than 2020, worse than Python, genuinely not bad).

How to Use This Book

The chapters are mostly independent. If you need Python integration right now, go to the Python chapter. If you’re building a REST API, go to REST. If you’ve never thought much about what happens on the wire when Q processes talk to each other, the IPC chapter is worth reading before anything that involves network communication.

If you’re starting fresh and don’t know which integration you need, the quick guide:

You want to…Go to…
Query kdb+ from PythonPython — use pykx
Build a Rust service that reads kdb+ dataRust — use kdbplus IPC
Do statistical research in R on kdb+ dataR — use rkdb
Expose kdb+ data as a REST APIREST — FastAPI gateway
Set up a real IDE for Q developmentIDEs — VS Code + KX extension
Understand Q’s wire protocolIPC
Serve live data to a browser dashboardStreaming — WebSockets
Integrate with KafkaStreaming — Kafka section
Add linting and testing to a Q codebaseDev Tooling

What This Book Assumes

You know Q. Not necessarily at guru level, but you can write a functional update, you know why select beats a loop, and you’ve debugged a type error at least once by adding backtick casts until it stopped complaining.

You know at least one of: Python, Rust, or R. Ideally more. You’ve worked with at least one web framework. You understand what a TCP socket is.

You’ve wondered at least once why Q can’t just have a decent package manager. (It can’t. This book doesn’t fix that.)

The IPC Foundation

One concept runs through every chapter: Q’s IPC protocol. Every library covered here — pykx, qPython, kdbplus, rkdb — is ultimately speaking this protocol. Understanding it once, at a conceptual level, makes everything else clearer.

Q communicates over TCP. A kdb+ process is always one of:

  • A server: listening on a port, handling incoming connections
  • A client: connecting to a server and sending queries
  • A gateway: doing both (and ideally doing it without being a single point of failure)

The port is set with the -p flag at startup:

q -p 5001

From another Q process:

/ Open a handle to a remote process
h: hopen `::5001
/ or with auth: h: hopen `::5001:user:pass

/ Synchronous call — blocks until remote returns
result: h "select count from trade where date=.z.d"

/ Safer: function + arguments rather than string eval
result: h (`.myns.myFunc; arg1; arg2)

/ Asynchronous — returns immediately, no response
neg[h] ".u.upd[`trade; data]"

/ Close when done
hclose h

The synchronous call blocks the calling process. The asynchronous (negative handle) variant does not wait for a response — used by tickerplants to publish to subscribers. The IPC chapter covers both in detail, along with message handlers, gateway patterns, and the situations where a synchronous call will hang your process and ruin your day.

Every integration library in this book provides an abstraction over this mechanism. When something breaks, stripping the abstraction and thinking about what’s happening at the handle level is usually how you find the bug.

The Type System Across Boundaries

Q’s type system is the source of most integration friction. A brief orientation:

Q typeBytesPython (pykx)R (rkdb)JSON
boolean1boollogicaltrue/false
short2np.int16integernumber
int4np.int32integernumber
long8np.int64numeric*number
float8np.float64numericnumber
symbolvarstrcharacterstring
timestamp8np.datetime64[ns]POSIXctstring (ISO 8601)
date4datetime.dateDatestring
char listvarstrcharacterstring
tablepd.DataFramedata.framearray of objects

*R has no 64-bit integer. Q longs larger than 2³¹ lose precision silently when received in R.

The timestamps column deserves emphasis: Q timestamps are nanoseconds since 2000-01-01. Python datetimes are microsecond-resolution since 1970-01-01. Every library converts for you, but the conversion can drop nanoseconds silently (Python’s datetime has no nanosecond field) or produce unexpected values if you’re not using the right output format. Each language chapter calls out the specific gotcha.

A Note on Versions

This book targets kdb+ 4.1 and the 2025–2026 versions of the libraries discussed. Where a library has changed significantly or has a version-specific gotcha, it’s called out inline.

The free 64-bit on-demand license from KX works for everything in this book. Get it at kx.com/developers/download-licenses/. The license requires internet connectivity for validation — relevant if you’re planning air-gapped deployments, which need a commercial license.

Setting Up a Base Environment

If you’re starting fresh:

# macOS (Apple Silicon)
mkdir -p ~/q
# Download from kx.com: macosx.zip for Intel, macosarm.zip for Apple Silicon
unzip macosarm.zip -d ~/q
echo 'export PATH="$HOME/q/m64:$PATH"' >> ~/.zshrc
source ~/.zshrc

# Linux x86-64
mkdir -p ~/q
# Download: linuxx86.zip
unzip linuxx86.zip -d ~/q
echo 'export PATH="$HOME/q/l64:$PATH"' >> ~/.bashrc
source ~/.bashrc

# Verify: start a q process on port 5001
q -p 5001
# You should see the q prompt: q)
# Test: q) 2 + 2
# 4
# Exit: q) \\

Each subsequent chapter has its own setup section for the specific integration. We won’t front-load dependencies — install things when you need them.

A minimal test that your q process is accepting IPC connections, from a second terminal:

# Quick connectivity test using bash and /dev/tcp
# (This is just to verify the port is open, not a real client)
echo "" > /dev/tcp/localhost/5001 && echo "Port 5001 is open"

# Or with nc:
nc -zv localhost 5001

And from a second q process:

h: hopen `::5001
h "1b"   / should return 1b
hclose h

The Philosophy

The goal is not to make Q look like Python. Q developers who want Python should write Python. The goal is to make Q work with Python — and Rust, and R, and Kafka, and REST clients — without losing what makes Q worth using: its speed on columnar time-series data, its expressive query syntax, its tick infrastructure.

Q as a database. Q as a compute engine. Q as a streaming backbone. Everything else as a consumer, a producer, or an orchestrator.

That’s the architecture this book is building toward. Each chapter adds one more connection point. By the end, you’ll have a Q process that’s no longer a silo — it’s the center of something.

Let’s build it.