In late 2024, Amazon announced that QLDB — Quantum Ledger Database — would reach end-of-support on July 31, 2025. For anyone building systems with QLDB at the core, this was a significant architectural decision: migrate before the deadline or design around it from the start.
We were in the design phase when the announcement dropped. TrustWarden's AgentLedger — the immutable audit trail for every AI agent action — needed QLDB-equivalent properties: tamper-evident, append-only, cryptographically verifiable. We chose to build on S3 Object Lock instead. Here is the design and the reasoning.
What QLDB actually provided
QLDB's core value proposition was the journal: an append-only, immutable log where every change could be cryptographically verified via a hash chain. Each block in the journal included a hash of its predecessor — forming a chain where tampering with any block invalidated all subsequent hashes. QLDB maintained this chain automatically and provided a GetDigest API for external verification.
The problem, beyond deprecation, was also architecture: QLDB was a managed service but not serverless in the Lambda sense. It maintained persistent connections via a custom QLDB driver and had its own query language (PartiQL with ledger extensions). For a fully Lambda-native architecture, it was already a slight mismatch.
S3 Object Lock: WORM storage at AWS scale
S3 Object Lock provides Write Once, Read Many (WORM) storage with two retention modes:
- Governance mode: objects cannot be deleted or modified except by users with the s3:BypassGovernanceRetention IAM permission.
- Compliance mode: objects cannot be deleted or modified by any user — including the root account — until the retention period expires. This is the mode we use.
In Compliance mode, once a ledger event is written to S3, it is physically immutable until its retention period expires. This is a stronger guarantee than QLDB's hash chain: the hash chain proves tampering occurred, but it does not prevent deletion. S3 Object Lock in Compliance mode prevents the deletion itself.
The full ledger design
An immutable store alone is not enough — you need to query it. S3 is not a database. Our AgentLedger uses two stores in tandem:
AgentLedger
├── S3 (Object Lock, Compliance mode) ← immutable, tamper-proof storage
│ └── /ledger/{year}/{month}/{day}/{event_id}.json.gz
│
└── DynamoDB (queryable index) ← fast retrieval
├── PK: agent_id
├── SK: timestamp#event_id
└── GSI: action, outcome, resourceEvery event is written to both stores. S3 is the authority — the source of truth. DynamoDB is the index — the fast query path. If DynamoDB is ever corrupted or lost, the full ledger can be reconstructed from S3.
KMS signing: cryptographic proof on every event
S3 Object Lock prevents deletion. But it does not prevent someone with write access from replacing an object before Object Lock takes effect. Our defense: every event is signed with a KMS asymmetric key before it is written to S3.
{
"event_id": "evt_01HN2K7XM4R9P3Q8V5W6Y",
"sequence_number": 47291,
"previous_hash": "sha256:a3f8b2d1e9c7...",
"agent_id": "agt_01HN2K6ZR3M8P9Q4V5W",
"agent_identity": "spiffe://trustwarden/acme-corp/finance/payment-processor/inst-x7k2m",
"action": "write:database:transactions",
"resource": "postgres://prod.acme-corp.internal/ledger",
"timestamp": "2026-03-11T10:32:11.847Z",
"outcome": "success",
"signature": "sha256WithRSA:3045022100...",
"context": {
"task_id": "task_01HN2K7XM",
"triggered_by": "orchestrator-agent-id",
"policy_version": "v2.1.0"
}
}The signature covers all fields. Any modification to any field — including the signature itself — is detectable. The signing key ARN is stored alongside the event for verification. CloudTrail records every kms:Sign call with the caller identity and timestamp.
QLDB vs S3 Object Lock + DynamoDB + KMS
- Tamper-evident: QLDB uses a hash chain. Our design uses KMS signatures plus a previous_hash field. Both detect tampering.
- Tamper-proof: QLDB cannot prevent deletion by AWS support or a rogue admin. S3 Object Lock Compliance mode prevents deletion by anyone including root, until retention expires.
- Queryable: QLDB has PartiQL. We use DynamoDB GSIs — simpler query patterns, lower latency at scale.
- Serverless: QLDB required persistent connections. S3 and DynamoDB are fully serverless — no connection pool management in Lambda.
- Service risk: QLDB is deprecated (end-of-support July 2025). S3 and DynamoDB are AWS's highest-SLA foundational services — no service risk.
- Cost: at high volume, the S3 + DynamoDB model is significantly cheaper than QLDB per-IO pricing.
The hash chain
We kept the hash chain concept from the QLDB design. Each event includes a previous_hash field containing the SHA-256 hash of the preceding event. This provides a second layer of tamper detection: even if someone somehow bypassed Object Lock, the chain would be broken.
The sequence number provides total ordering per agent. A gap in sequence numbers indicates a missing event. A broken hash chain indicates a modified event. Both conditions trigger an immediate alert.