Upgrading
Celeriant is pre-1.0: releases so far are 0.1.0, 0.1.1, 0.1.2 and 0.2.0. Releases ship as the container image ghcr.io/celeriant/celeriant, one tag per version; there are no prebuilt binaries. There is no written compatibility policy and no upgrade procedure in the server repo. This page describes what the code actually checks, and the rolling procedure that the failover mechanics support.
What the server checks
Immutable settings. On boot the node compares its flags with server_meta.toml in --data-root and refuses to start on a mismatch. Carry the same --num-shards, --routing-rule, --timestamp-precision, --timestamp-epoch-offset-secs, --reserve-coordinator-shard, --wal-compression-level and --wal-dictionary-name across the upgrade. See configuration.
On-disk format. Every block on disk carries a CRC and a format version. Each reader accepts exactly one version per block type and rejects anything else with UnsupportedVersion. There is no migration code. If a release bumps a block version, the new binary will not read the old WAL. No release so far has: the block versions are identical in every tag from 0.1.0 to 0.2.0.
Client wire protocol. The server accepts two frame encodings, V2 (bincode) and V3 (MessagePack), and rejects any other version. A connection's first message pins its version for the life of the connection. There is no release-version handshake, so a client keeps working across a server upgrade as long as both encodings stay supported.
Between the two nodes. Replication and heartbeats use V2 frames. Neither node checks the other's release version. Nothing stops a mixed-version pair, and nothing verifies one either.
Rolling upgrade, two nodes
Upgrade the follower first so there is one failover, not two.
- Check health. One node reports
celeriant_node_role1, andceleriant_replication_s3_fallbacks_totalis flat. See Monitoring. - Stop the follower. The leader keeps accepting writes and replicates them through S3 while the follower is gone. Writes are slower but still land on two systems.
- Start the follower on the new version. It boots, catches up from the S3 fallback batches and the leader, and rejoins.
- Wait for it to settle. S3 fallbacks stop, and
celeriant_wal_seqper shard matches the leader. Then wait at least--s3-lease-duration-ms(30 s by default) more. When the follower dropped, the leader renewed its lease in S3. Until that renewal expires, the follower will not challenge for the lease, and step 5 turns into a write outage as long as the time left on it. - Stop the leader. There is no graceful handover: shutdown does not release the lease. The follower's heartbeat lease expires after
--heartbeat-lease-duration-ms(1500 ms by default), it takes the lease with a conditional write in S3, and it promotes. Writes are rejected until promotion finishes. - Start the old leader on the new version. It finds a valid lease held by the other node and joins as follower.
Writes in flight when the leader stops may have been applied without an answer reaching the client. Make writes idempotent so the client can retry them safely.
Single node
A standalone node has nowhere to fail over to. Stop it, swap the image or binary, start it. Boot re-checks O_DIRECT and validates server_meta.toml before opening the WAL. Plan for the write outage.
0.2.0 notes
- The node ID is now derived from
private_keyon every start, and the public key file is no longer read. An upgraded node keeps its identity as long asprivate_keyis intact. - The breaking changes are in the Rust client API (
ClientErrorvariants,build_frame,ListOperations::new), not the server or the wire. See the server repo's CHANGELOG.
Mixed-version clusters and downgrades are untested. Read the CHANGELOG for each release, rehearse the upgrade on a copy of the data, and keep a backup you have restored.