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.