Skip to content

Encryption

The encryption extension defines a codec architecture for encrypting job payloads at the client before they reach the backend. This ensures sensitive job arguments are protected at rest and in transit through the backend infrastructure.

The codec interface provides a composable encryption and compression pipeline:

encode(payload) → encrypted_payload
decode(encrypted_payload) → payload

Codecs are applied in order during encode and reversed during decode.

By default, only the args field is encrypted. Routing fields remain in plaintext so the backend can process the job:

FieldEncryptedReason
argsYesContains application data
typeNoNeeded for routing to handlers
queueNoNeeded for queue placement
idNoNeeded for job tracking
priorityNoNeeded for ordering
scheduled_atNoNeeded for scheduling
metaPartiallyCodec metadata added; other meta encrypted optionally

OJS specifies AES-256-GCM as the required encryption algorithm:

  • Algorithm: AES-256-GCM (authenticated encryption with associated data)
  • Key size: 256 bits
  • Nonce: Random 96-bit (12-byte) nonce per job
  • Wire format: [1 byte version][12 bytes nonce][N bytes ciphertext][16 bytes GCM tag]

An encrypted job includes codec metadata:

{
"id": "01961234-5678-7abc-def0-123456789abc",
"type": "payment.process",
"queue": "payments",
"args": "AQAAAAxr4nJk8f2...",
"ojs_encoded": true,
"meta": {
"ojs.codec.encodings": ["aes-256-gcm"],
"ojs.codec.key_id": "key-2026-02"
}
}
MarkerDescription
ojs_encodedBoolean flag indicating the job has been encoded
meta.ojs.codec.encodingsOrdered list of codecs applied
meta.ojs.codec.key_idIdentifier of the encryption key used

Multiple codecs can be chained. For example, compress then encrypt:

encode: compress(zstd) → encrypt(aes-256-gcm)
decode: decrypt(aes-256-gcm) → decompress(zstd)
{
"meta": {
"ojs.codec.encodings": ["zstd", "aes-256-gcm"]
}
}
CodecDescription
zstdRecommended. Best compression ratio for structured data.
gzipWidely supported. Good for interoperability.
snappyFastest compression/decompression. Lower ratio.

Keys can be rotated without re-encrypting existing jobs:

  1. Add the new key to the key store.
  2. Set the new key as the default for encoding.
  3. Keep old keys available for decoding (referenced by meta.ojs.codec.key_id).
  4. Old keys can be retired after all jobs encrypted with them have completed.

Key storage options: environment variables, secrets managers (AWS KMS, HashiCorp Vault), or mounted files.

For tools that need to view encrypted job data (admin dashboards, CLIs), a standalone Codec Server provides HTTP-based decode:

Terminal window
POST /decode
Authorization: Bearer <jwt>
{
"args": "AQAAAAxr4nJk8f2...",
"meta": {
"ojs.codec.encodings": ["aes-256-gcm"],
"ojs.codec.key_id": "key-2026-02"
}
}

The Codec Server requires authentication and enforces per-user access control.

Unique job deduplication keys are computed on the plaintext args before encryption. This is enforced by middleware ordering—the unique middleware runs before the encryption middleware in the enqueue chain.