Skip to main content

Storage Format

This page documents the storage layout used by rabbitmq-backup, the RBAK binary segment format, and the manifest JSON schema.

Storage Layout

Every backup is stored under a {backup_id}/ prefix in the configured storage backend. The directory structure is:

{prefix}/{backup_id}/
├── manifest.json
├── definitions/
│ ├── definitions.json.zst
│ └── rollback-before-import-<timestamp>.zst
├── state/
│ └── offsets.db
└── queues/
└── {vhost}/
└── {queue_name}/
├── segment-0001.zst
├── segment-0002.zst
└── segment-NNNN.zst

Path Components

ComponentDescription
{prefix}Optional storage prefix from the storage.prefix configuration field.
{backup_id}The backup_id from the configuration file (e.g. prod-daily-2025-04-10).
manifest.jsonBackup manifest containing metadata about all queues, segments, and definitions.
definitions/definitions.json.zstCompressed RabbitMQ definitions export (topology, users, policies). Extension matches the compression algorithm: .zst for zstd, .lz4 for LZ4, or no extension for uncompressed.
definitions/rollback-before-import-<timestamp>.<ext>Target-cluster definitions snapshot written immediately before a full restore imports backed-up definitions. Used for manual rollback/recovery.
state/offsets.dbSQLite checkpoint database for resumable backups (synced from local to remote when configured).
queues/{vhost}/{queue_name}/Per-queue directory containing message segments.
segment-NNNN.zstIndividual segment file. NNNN is a zero-padded 4-digit sequence number.

Vhost Encoding

The default vhost / is encoded as _default in storage paths to avoid path separator conflicts:

VhostStorage Path
/queues/_default/orders/segment-0001.zst
productionqueues/production/orders/segment-0001.zst

Checkpoint State

Checkpoint state is stored in SQLite. Backup checkpoints track:

  • queue progress by backup_id, vhost, and queue_name
  • last completed segment sequence
  • target message count for the run
  • whether the queue or stream completed
  • stream offsets for stream queues

For object storage, offset_storage.s3_key syncs the SQLite database to remote storage, commonly under {backup_id}/state/offsets.db.

Restore checkpoints are local files configured with restore.checkpoint_state. They track processed records per queue so interrupted restores can be rerun without duplicating completed queues.

File Extension Convention

CompressionExtension
zstd.zst
LZ4.lz4
None(no extension)

Manifest JSON Schema

The manifest is stored at {backup_id}/manifest.json and contains the complete metadata for a backup. It is written as the final step of a backup operation.

BackupManifest

{
"backup_id": "prod-daily-2025-04-10",
"created_at": 1712756400000,
"completed_at": 1712756535000,
"source_cluster": "rabbit@node1",
"rabbitmq_version": "3.13.2",
"backup_tool_version": "0.1.0",
"definitions": { ... },
"queues": [ ... ],
"total_messages": 2621,
"total_bytes": 905216,
"total_segments": 4
}
FieldTypeNullableDescription
backup_idstringNoUnique identifier matching the config.
created_ati64 (epoch ms)NoTimestamp when the backup started.
completed_ati64 (epoch ms)YesTimestamp when the backup completed. null if the backup was interrupted.
source_clusterstringYesCluster name from the Management API /api/overview.
rabbitmq_versionstringYesRabbitMQ version from the Management API.
backup_tool_versionstringNoVersion of rabbitmq-backup that created this backup.
definitionsobjectYesMetadata about the definitions export. See DefinitionsBackup.
queuesarrayNoPer-queue backup metadata. See QueueBackup.
total_messagesu64NoSum of all queue message counts.
total_bytesu64NoSum of all segment sizes (compressed).
total_segmentsu64NoTotal number of segment files.

DefinitionsBackup

{
"key": "backup-001/definitions/definitions.json.zst",
"vhost_count": 2,
"queue_count": 5,
"exchange_count": 8,
"user_count": 3,
"size_bytes": 4300
}
FieldTypeDescription
keystringStorage key for the compressed definitions file.
vhost_countusizeNumber of virtual hosts in the definitions.
queue_countusizeNumber of queues.
exchange_countusizeNumber of exchanges.
user_countusizeNumber of users.
size_bytesu64Uncompressed size of the definitions JSON.

QueueBackup

{
"vhost": "/",
"name": "orders",
"queue_type": "classic",
"segments": [ ... ],
"message_count": 1542,
"first_message_timestamp": 1712700000000,
"last_message_timestamp": 1712756400000
}
FieldTypeNullableDescription
vhoststringNoVirtual host of the queue.
namestringNoQueue name.
queue_typestringNoQueue type: classic, quorum, or stream.
segmentsarrayNoList of segment metadata. See SegmentMetadata.
message_countu64NoTotal messages backed up from this queue.
first_message_timestampi64 (epoch ms)Yesbacked_up_at timestamp of the first message.
last_message_timestampi64 (epoch ms)Yesbacked_up_at timestamp of the last message.

SegmentMetadata

{
"key": "backup-001/queues/_default/orders/segment-0001.zst",
"sequence": 1,
"record_count": 1000,
"size_bytes": 348160,
"uncompressed_bytes": 1048576,
"first_timestamp": 1712700000000,
"last_timestamp": 1712720000000,
"checksum": "a1b2c3d4e5f6...64-char-sha256-hex..."
}
FieldTypeNullableDescription
keystringNoStorage key for the segment file.
sequenceu64NoMonotonically increasing sequence number within the queue.
record_countu64NoNumber of message records in this segment.
size_bytesu64NoCompressed segment size (header + payload + footer).
uncompressed_bytesu64NoUncompressed payload size (before compression).
first_timestampi64 (epoch ms)Yesbacked_up_at timestamp of the first record.
last_timestampi64 (epoch ms)Yesbacked_up_at timestamp of the last record.
checksumstringNoSHA-256 hex digest of the complete segment file (header + compressed payload + footer).

RBAK Segment Format

Each segment file uses a custom binary format with a 32-byte header, a compressed payload, and an 8-byte footer.

Overview

┌──────────────────────────────────┐
│ Header (32 bytes) │
├──────────────────────────────────┤
│ Compressed Payload (var) │
│ [length-prefixed JSON records] │
├──────────────────────────────────┤
│ Footer (8 bytes) │
└──────────────────────────────────┘

Header (32 bytes)

OffsetSizeFieldDescription
04MagicASCII RBAK (0x5242414B). Identifies the file as an RBAK segment.
41VersionFormat version. Currently 1.
51CompressionCompression algorithm: 0 = none, 1 = zstd, 2 = LZ4.
62ReservedReserved for future use. Set to 0x0000.
88Record CountLittle-endian u64. Number of message records in the payload.
168First TimestampLittle-endian i64. backed_up_at epoch milliseconds of the first record.
248Last TimestampLittle-endian i64. backed_up_at epoch milliseconds of the last record.

Compressed Payload

The payload is the compressed form of a sequence of length-prefixed JSON records. Before compression, the payload is structured as:

┌─────────────────────┐
│ len₁ (4 bytes, LE) │ ← u32 length of JSON₁
│ JSON₁ (len₁ bytes) │ ← BackupRecord serialized as JSON
├─────────────────────┤
│ len₂ (4 bytes, LE) │
│ JSON₂ (len₂ bytes) │
├─────────────────────┤
│ ... │
├─────────────────────┤
│ lenₙ (4 bytes, LE) │
│ JSONₙ (lenₙ bytes) │
└─────────────────────┘

Each record is a BackupRecord serialized as JSON:

{
"body": [104, 101, 108, 108, 111],
"properties": {
"content_type": "application/json",
"content_encoding": null,
"delivery_mode": 2,
"priority": null,
"correlation_id": "corr-123",
"reply_to": null,
"expiration": null,
"message_id": "msg-456",
"timestamp": 1712756400,
"type_field": "order.created",
"user_id": null,
"app_id": "my-service",
"cluster_id": null
},
"headers": [
["x-retry-count", {"Long": 3}],
["x-source", {"LongString": "api-gateway"}]
],
"exchange": "orders.exchange",
"routing_key": "order.created",
"delivery_tag": 42,
"redelivered": false,
"backed_up_at": 1712756400123,
"source_queue": "orders",
"source_vhost": "/"
}

BackupRecord Fields

FieldTypeDescription
body[u8] or nullMessage body as a byte array. null for zero-length bodies.
propertiesobjectAMQP basic properties (see BackupProperties below).
headersarray of [key, value]AMQP message headers from basic.properties.headers.
exchangestringExchange the message was published to. Empty string for stream messages.
routing_keystringRouting key. Empty string for stream messages.
delivery_tagu64Delivery tag from the broker (or stream offset for stream queues).
redeliveredboolWhether the broker marked the message as redelivered.
backed_up_ati64 (epoch ms)Timestamp when this record was captured by the backup tool.
source_queuestringQueue name this message was read from.
source_vhoststringVhost of the source queue.

BackupProperties Fields

FieldTypeDescription
content_typestring or nullMIME content type (e.g. application/json).
content_encodingstring or nullContent encoding (e.g. utf-8, gzip).
delivery_modeu8 or null1 = non-persistent, 2 = persistent.
priorityu8 or nullMessage priority (0-255).
correlation_idstring or nullCorrelation identifier.
reply_tostring or nullReply-to queue/address.
expirationstring or nullMessage TTL in milliseconds (as string).
message_idstring or nullApplication-level message identifier.
timestampi64 or nullAMQP timestamp (seconds since epoch).
type_fieldstring or nullMessage type (application-defined).
user_idstring or nullPublishing user.
app_idstring or nullPublishing application.
cluster_idstring or nullCluster identifier (deprecated in AMQP).

BackupHeaderValue Variants

VariantJSON RepresentationDescription
LongString{"LongString": "value"}AMQP long string.
ShortString{"ShortString": "value"}AMQP short string.
Long{"Long": 42}64-bit integer.
Short{"Short": 5}16-bit integer.
Bool{"Bool": true}Boolean.
Bytes{"Bytes": [1, 2, 3]}Raw byte array.
Timestamp{"Timestamp": 1712756400}AMQP timestamp.
Float{"Float": 3.14}32-bit float.
Double{"Double": 3.14159}64-bit float.
Void"Void"Null/void value.
Table{"Table": [[key, value], ...]}Nested field table.
Array{"Array": [value, ...]}Field array.
OffsetSizeFieldDescription
N-84CRC32Little-endian u32. CRC32 checksum of all preceding bytes (header + compressed payload). Computed using crc32fast.
N-44End MagicASCII KABR (0x4B414252). Reverse of the start magic; signals the end of the segment.

Integrity Verification

Segment integrity is verified in two stages:

  1. CRC32 check: The CRC32 in the footer is computed over all bytes from offset 0 to len - 8 (header + compressed payload). On read, the actual CRC32 is recomputed and compared against the stored value.

  2. SHA-256 check: The SHA-256 digest of the entire segment file (header + compressed payload + footer) is stored in the manifest's SegmentMetadata.checksum field. The validate --deep command verifies this.


Storage URL Formats

The list, describe, and validate commands accept storage paths in URL format. The from_url parser supports:

SchemeFormatExample
S3s3://bucket?region=...&endpoint=...s3://my-bucket?region=us-east-1
Azureazure://account.blob.core.windows.net/containerazure://myaccount.blob.core.windows.net/backups
GCSgcs://bucketgcs://my-gcs-bucket
Filesystemfile:///pathfile:///var/lib/rabbitmq-backup/data
Memorymemory://memory://

Query parameters for S3 URLs:

ParameterDescription
regionAWS region
endpointCustom endpoint URL
path_styleSet to true for path-style requests

Definitions File Format

The definitions file at {backup_id}/definitions/definitions.json.zst is a compressed JSON export from the RabbitMQ Management API. When decompressed, it follows the standard RabbitMQ definitions JSON format:

{
"rabbit_version": "3.13.2",
"rabbitmq_version": "3.13.2",
"vhosts": [...],
"users": [...],
"permissions": [...],
"exchanges": [...],
"queues": [...],
"bindings": [...],
"policies": [...],
"parameters": [...],
"global_parameters": [...]
}

This is the same format used by rabbitmqadmin export and the Management API GET /api/definitions endpoint.