Pre-1.0 hoardDB is pre-1.0. Expect breaking changes.

Compatibility and versions

What you can rely on when you upgrade hoardDB: what talks to what, what is read back from disk, what happens when you run two builds at once, which platforms are built, and how a feature is retired.

hoardDB is pre-1.0 and no release has been tagged yet. Where this page says “today”, it describes the build in the repository. Where it states a rule, the rule is the project’s commitment from v1.0 on.

What carries a version

Three things are versioned, separately from the release number, because they have different consequences when they change.

WhatWhere you see itToday
Wire protocolhoarddb-server -v and hoarddb -v print protocol=N; the TLS handshake negotiates hoarddb/Nmajor 1
Data directoryChecked by the server at startstorage layout version 2 (the shared store)
Dump formatformat_version in a dump’s manifest.json and each bucket’s metadata.json3 (format 2 still restores)

The release (or devel for an untagged build) is printed by -v too:

hoarddb-server -v
hoarddb-server version=devel commit= build_date= protocol=1

The wire protocol

A client and a server speak the same protocol major or they do not talk.

  • The major is negotiated before anything is sent. Both sides offer hoarddb/1 in the TLS handshake (the ALPN identifier), and every frame also carries the version in its header, so a connection can never mix versions.
  • A mismatch is named, not left to a decode failure later. A client that offers no major the server serves is refused in the handshake, and one that states a different major at login gets server speaks protocol 1, client sent 2.
  • Inside a major, change is additive only. New operations, new optional fields and new capability names can appear. A client ignores fields it does not know, and a server ignores capability names it does not know. A server that is asked for an operation it does not have answers unsupported opcode and the opcode’s number, never silence.
  • A breaking change gets a new major. It is never a silent reinterpretation of hoarddb/1. The server keeps serving the previous major for at least one release after a new one ships, and warns on every connection that uses the old one, with the date it will stop.

Today only major 1 exists, so no client has had to move yet. The one thing to check when you mix versions is the line above: hoarddb -v and hoarddb-server -v should print the same protocol=.

The data directory

The server reads what is on disk at start and refuses what it does not understand, instead of guessing:

  • The storage layout. This build keeps every bucket in one shared store per node. A data directory written by the earlier layout (it has a catalog.json of its own) is refused at start with a message that says so, and is not converted in place. Back it up with the earlier build’s hoarddb dump, then restore into a fresh data directory on this build. See Backup and restore.
  • users.json. It carries its own format_version (today 1), and a file with another version is refused. It is sealed under a key your backups must keep; see User management.
  • Encryption. A node’s encryption mode is fixed when its data directory is first started. A data directory started with encryption on is refused by a server configured without it, and the reverse; see Configuration.
  • Sealed credential files. On a node with encryption at rest, the cluster token, the signing key and the TLS private key are sealed under the node key. A node that finds them in plaintext seals them in place at its next start, and that is one-way: a build from before this release cannot read a sealed file, so do not start the data directory with it. A sealed file belongs to its node; copy a token to a new node with get-token, not by copying the file. See Security.
  • The write-ahead log. A log written by an earlier build is read as it is, with nothing to convert; the entries this build adds to it carry more than the earlier ones did.
  • The memtable size a store chose at its first start is saved with the store and kept on every restart (store/memtable-choice.json).
  • Dumps. restore accepts the dump format it writes (format_version 3) and format 2, which a build before the dead-entry section wrote, and refuses any other with the version on both sides in the message. There is no format 1 to restore. A format 3 dump may carry a <bucket>.dead.bson file for a queue’s or heap’s dead entries; a restore keeps them dead.

Upgrade every member before a node publishes a client address

A cluster member that sets tcp.advertise (or listens on an address other machines can dial) writes that address into the cluster state. A member running an earlier build cannot read a cluster command or snapshot that carries it: it stops applying changes, its view of the cluster stays behind for good, and it cannot restart from a snapshot taken after the address was written. There is no negotiation between builds before the first release. Upgrade every member first, then add or restart the nodes that publish an address. A member that has already stopped advancing is repaired by replacing it (join --replace).

Going back is not supported

A node that has written to its log on a newer build cannot be started on an older one. The older build opens the data directory but reads the newer log entries as a damaged tail and discards them, and after a crash the copies of a bucket can silently disagree about writes that were acknowledged. The first time a node writes the newer format it logs one line saying so.

A node that keeps a write-ahead log (a replication factor above 1, or seed nodes) writes it in segment format 2 from its first start on this build, whatever storage.wal_preallocate says, and an earlier build refuses to start on it instead of discarding it: it stops with an error that ends parsing sealed file header: flags must be 0x00, got 01 at offset 6 (03 on a sealed node) and changes nothing. That error means this data directory was written by a newer hoardDB: start the newer build, or restore the copy taken before the upgrade. The log’s segment format is not the setting: storage.wal_preallocate only turns the zero fill on. Changing that setting is a rolling restart of the same build: change it on one node and restart it, wait until hoarddb_replication_peers_not_in_sync is 0 and status shows the expected WAL row, then do the next. Upgrading to the build that introduces format 2 is not a rolling operation: stop every node, copy each data directory, install, start, as below.

So the way back is a backup, not the old binary: copy the whole data directory before you upgrade, and go back by restoring that copy on every node. Limitations and Replication have the details.

Upgrading

No tagged release exists yet, so there is no earlier release to upgrade from. This is the procedure the current builds require, and it is the one to follow for every upgrade that touches a data directory.

  1. Stop writes and wait one minute. An earlier build has no gauge that tells you the log has caught up, so the wait is the margin.
  2. Stop every node.
  3. Copy each node’s whole data directory. dump is not a substitute: it leaves out blob payloads and user accounts. A copy of the directory keeps both.
  4. Install the new build on every node.
  5. Start every node. Check hoarddb-server -v on each, then status and nodes from the CLI. The new build reads each node’s log as the earlier build left it.

Rolling upgrades

A cluster is not upgraded one node at a time. Do not run two builds side by side in one cluster. Builds can disagree about where a bucket lives, and nothing detects that disagreement; and a node that runs an earlier build cannot pull data from an upgraded node until it is upgraded too. Data is pulled when a node joins, when one is removed, when the cluster rebalances and when you run migrate, so a cluster of mixed builds can stall in the middle of one of those.

The rule that follows: upgrade every node to the same build before you add a node, remove one or run migrate, and if you find a cluster of mixed builds, finish the upgrade first. Upgrading a cluster one node at a time, with no outage, is planned for v1.1. Until a release says it is delivered, the stop-all rule above is the only supported procedure.

Supported platforms

The server and the CLI are released for two platforms:

Operating systemArchitecture
Linuxamd64, arm64

Windows is supported through WSL2, using the Linux binaries. The server and the CLI do not compile for native Windows, so there is no .exe to build. macOS is not supported natively in this release; on a Mac, run the Docker image. Native macOS is planned for v1.2.

What “supported” means, precisely: the platform build produces each file and checks that it is the architecture its name says (see Installation), and the captured session in Getting started was run end to end on linux/amd64. A platform outside that table (macOS, for instance) may compile, but it is not tested or supported before v1.2.

Building from source needs the Go version named in go.mod (Go 1.26.9 at the time of writing).

How a feature is retired

The rule (and the reason for it): hoardDB never breaks your data or your programs silently. Trust is the whole product.

  • Deprecate loudly. A feature that is going away — a setting, a CLI verb or flag, an HQL statement, a configuration key — is deprecated in a minor release and keeps working until the next minor release and at least 90 days after the deprecation shipped, whichever is later. Each time it is used it prints a warning on standard error that names what to use instead and the date the old way stops. Removing a deprecated feature does not need a major release; the removal is listed under Removed in the release notes.
  • Version explicitly. A change a program could notice — a wire change, a changed meaning of a setting, a new on-disk layout — is named in the release notes under what changed and what to do about it, and a wire change raises the protocol major as described above.
  • Refuse, do not guess. When an old form is no longer accepted, it fails with a message that says what replaced it. For example, the old define bucket statement is refused on purpose with the text define was renamed: use 'create bucket <name> { type: hash }', so an old script stops at once instead of doing something different.
  • Never lose data on the way. An upgrade that cannot read your data stops and says so. It does not discard what it does not understand.

Before v1.0 this was not always possible. Changes made before a release — for instance, the environment variable prefix that became HOARDDB_ — were made without a deprecation period, and the release notes record them. From v1.0 the rules above apply.

Source: docs/user/compatibility.md in the repository.