---
title: "HeliosDB Nano v3.22 → v3.30 — Eight Releases of Postgres-Compat, Auth, and psql Tooling"
description: "Eight Nano releases closed the gaps most evaluators hit in the first half-hour: SCRAM-SHA-256 with proper GS2 parsing, CREATE DATABASE + StartupMessage validation, information_schema completion, real \\d / \\l / \\dt, keyset row-constructor pagination, and FK enforcement on the index path. The unglamorous wire-protocol work that turns 'interesting' into 'drop-in'."
date: 2026-05-18
updated: 2026-05-18
tag: "Release"
canonical: https://www.heliosdb.com/blog/nano-3-22-to-3-30-postgres-compat-auth-psql.html
---

# HeliosDB Nano v3.22 → v3.30 — Eight Releases of Postgres-Compat, Auth, and psql Tooling

If you tried HeliosDB Nano a couple of months ago and bounced off because `psql \d` returned stubs, or because your JDBC driver couldn't authenticate, this is the post for you. Eight Nano releases between v3.22.1 and v3.30.0 closed the Postgres-compat gaps most evaluators hit in the first half-hour. Nothing flashy — just the unglamorous wire-protocol and meta-command work that turns "interesting" into "drop-in".

## SCRAM-SHA-256 with a proper GS2 header (v3.26.0)

Pre-v3.26.0, Nano implemented SCRAM-SHA-256 close enough that most clients worked, but a handful — recent `libpq`, modern JDBC, `pg8000` with `channel_binding=disable` — would refuse the handshake because the GS2 header on the client-first message wasn't being parsed strictly. v3.26.0 implements RFC 5802 GS2 parsing end-to-end. The wire shape, for the record:

```
client-first: n,,n=user,r=<client-nonce>
server-first:           r=<client-nonce + server-nonce>,s=<salt>,i=<iterations>
client-final: c=biws,r=<...>,p=<client-proof>
server-final: v=<server-signature>
```

The fix is in the `n,,` prefix — the empty authzid in particular — not the cryptographic core. Net effect: `psql`, `libpq`, JDBC, `pg8000`, SQLAlchemy, and Diesel all authenticate against a Nano server without configuration acrobatics.

## CREATE DATABASE / DROP DATABASE + StartupMessage validation (v3.25.0)

v3.25.0 added `CREATE DATABASE foo` and `DROP DATABASE foo` as first-class SQL statements, and — this is the load-bearing change — made the wire-protocol StartupMessage actually validate the requested database name. A client connecting with `dbname=acme_tenant_42` now lands in `acme_tenant_42` or gets `ERROR: database "acme_tenant_42" does not exist`. Previously the parameter was accepted but ignored, which made multi-tenant routing impossible from the wire.

This isn't multi-tenancy with row-level security — it's the simpler model where each tenant gets a logical database in one Nano process, selected at connection time. Combined with SCRAM-SHA-256, you can now run a tenant-per-database pool from any Postgres driver:

```
$ psql "host=nano.local user=app password=<...> dbname=tenant_42"
tenant_42=> SELECT current_database();
 current_database
------------------
 tenant_42
```

## information_schema completion (v3.24.0)

Before v3.24.0, Nano's `information_schema` covered `tables`, `columns`, and `key_column_usage`, but introspection tools that walked further hit empty views. v3.24.0 populates the remaining catalog surface:

- `information_schema.routines` — PL/pgSQL functions and stored procedures
- `information_schema.parameters` — routine signatures
- `information_schema.character_sets`, `collations` — encoding metadata
- `information_schema.view_table_usage`, `view_column_usage` — view dependency graph
- `information_schema.role_table_grants`, `role_column_grants` — GRANT introspection

The pragmatic effect: tools like DBeaver, DataGrip, and Drizzle's introspection command now produce complete schema dumps. Strict-unknown-view behaviour is preserved — a query against a view that doesn't exist returns a Postgres-shaped `undefined_table` error rather than an empty result, so tooling that gates on errors sees what it expects.

## Real \\d, \\l, \\dt in psql (v3.26.1)

The psql backslash commands are mostly client-side macros, but they expand into specific SQL queries against `pg_catalog` and `information_schema`. v3.26.1 wires the catalog views these commands hit to live data, so `\d`, `\l`, and `\dt` now return your actual schema instead of stubs. Migration scripts that pipe `psql -c '\dt' | awk ...` stop being a special case.

## Keyset row-constructor pagination (v3.23.0 → v3.30.0)

If you've ever pulled a million-row result set in 1 000-row pages and watched query time drift up linearly, you've felt the LIMIT/OFFSET problem — each page rescans the offset rows it's about to throw away. v3.23.0 wired up keyset cursors as a stateless alternative, and v3.30.0 extended them to compose across joins. The row-constructor form is a one-line edit:

```
-- Old (drifts under load)
SELECT * FROM events
ORDER BY created_at, id
LIMIT 1000 OFFSET 50000;

-- New (constant cost per page)
SELECT * FROM events
WHERE (created_at, id) > ('2026-04-30 14:22:00', 9981234)
ORDER BY created_at, id
LIMIT 1000;
```

Composes across joins from v3.23.0+, and from v3.30.0 the planner pushes the row-constructor predicate down through joined tables that share an index prefix. Worked examples and the side-by-side LIMIT/OFFSET comparison live on [pagination-performance](https://www.heliosdb.com/pagination-performance.html).

## FK enforcement on the index path (v3.30.0)

The v3.30.0 release moved `ON CONFLICT DO UPDATE` and `DELETE` on foreign-key parents off the SQL planner and onto direct index lookup. The change is uninteresting at one row and meaningful at scale — measured on representative bulk-load fixtures (10K rows, single transaction), the FK enforcement path is between two and three orders of magnitude faster than v3.22.x. Reproduce it on your own and report variance; the magnitude depends heavily on schema depth and index width.

## Upgrade path

For most users, v3.22.x → v3.30.0 is a drop-in upgrade — the data directory format hasn't changed in this window. The full matrix lives at [docs.heliosdb.com/docs/nano/guides/upgrade](https://www.heliosdb.com/docs/nano/guides/upgrade/) and covers the pre-3.6.0 dump/restore path for the genuinely-old upgraders. If you're on v3.22.x, just swap binaries and restart.

```
$ cargo install heliosdb-nano --version 3.30.0
$ heliosdb-nano start --data-dir ./data
HeliosDB Nano v3.30.0 listening on 127.0.0.1:5432 (PG) and 127.0.0.1:3307 (MySQL)
```

HeliosDB Nano is Apache 2.0. Repository: [github.com/dimensigon/HDB-HeliosDB-Nano](https://github.com/dimensigon/HDB-HeliosDB-Nano).
