Audit Logging for Compliance in Kafka
A complete, plain-English guide to building an audit trail that regulators, security teams and courtrooms can trust: what to record, how to protect it, how long to keep it, and how to prove nobody changed it.
Imagine a customer calls your bank and says, “I never sent that payment.” Someone now has to answer one simple question: who did what, to which account, and when? If your systems cannot answer that with certainty, you have a serious problem. Regulators can fine you. Auditors can refuse to sign off. Lawyers can lose cases that should have been easy to win.
That answer lives in something called an audit log. Apache Kafka, the popular system for moving streams of events between software services, is one of the best places to build one. It is fast, it keeps copies of data on several machines, and it remembers events for as long as you tell it to. But Kafka does not give you a compliant audit trail automatically. You have to design it with care.
This guide starts from zero. Every new word is explained the first time it appears, and every big idea comes with an everyday comparison. By the end you will know how to record the right events, get them into Kafka without losing any, protect private data inside them, prove they were never edited, and keep them for the years the law demands.
1What an Audit Log Is and Why Compliance Demands It
Before touching Kafka, we need to be clear about what we are building. An audit log is not the same thing as the messages your application prints while it runs.
Two very different kinds of logs
Most software writes application logs. These are notes for developers, such as “started payment job” or “database took 400 milliseconds to answer”. They help engineers fix bugs. Nobody promises to keep them for years, and nobody worries if a few lines go missing.
An audit log is different. It is a permanent, trustworthy record of who did what, to which thing, when, from where, and whether it worked. It is written for auditors, investigators and regulators. If an application log is a diary, an audit log is a signed receipt book.
Think of the security camera at a jewelry shop. The shop assistant chatting about the weather is an application log. The camera footage that shows exactly who opened the vault at 2:14 a.m. is an audit log. You keep the footage in a locked room, you never edit it, and you hand it to the police when they ask.
The five questions every audit record must answer
A useful audit record answers five simple questions. Security people call them the “who, what, when, where and outcome” of an event.
- Who acted: a person, a service account, or an automated job.
- What they did: read, create, change, delete, approve, log in, change a permission.
- On what: the customer record, the topic, the file or the setting that was touched.
- When and where: an exact timestamp and the system or network address involved.
- Outcome: whether the action succeeded, failed or was blocked, and why.
Why the law cares
Governments and industry bodies do not trust a company’s word alone. They ask for evidence. When something goes wrong, such as a data breach, a fraud case or a suspicious change to financial numbers, the audit log is the evidence. Without it, a company cannot prove what happened, cannot show it acted responsibly, and often cannot even tell which customers were affected.
Whenever you are unsure whether something belongs in the audit log, ask: “Would an investigator, six months from now, need this to reconstruct what happened?” If yes, it belongs.
2Kafka Basics in Plain English
You do not need to be a Kafka expert to follow this guide. Here are the handful of ideas that everything else builds on.
What Kafka is
Apache Kafka is a system for moving and storing streams of events. An event is just a small record that says “something happened”, for example “user 42 changed their email address”. Software components called producers write events into Kafka. Other components called consumers read them out, sometimes seconds later and sometimes months later.
Kafka was created at LinkedIn to carry activity data and operational data around a very large website, and it was later open sourced. Today companies such as Netflix, Uber and thousands of banks and retailers use it as the central nervous system between their services.
Picture a huge post office with endless numbered mail slots. Producers drop letters into a slot. Consumers walk up and read letters at their own pace, and the post office never throws a letter away until its time is up. Nobody has to wait for anybody else.
The building blocks
Topic
A named category of events, like “payments” or “audit-events”. Think of it as one labeled shelf in the post office.
Partition
A topic is split into partitions so many machines can share the load. Order is guaranteed inside one partition, not across all of them.
Offset
Each event in a partition gets a running number. It works like a page number that never changes.
Broker
A Kafka server that stores partitions and serves clients. A cluster is a team of brokers working together.
Replication
Every partition is copied to other brokers. If one machine dies, another holds an identical copy.
Consumer group
A team of consumers that share the reading work of a topic. Each partition is read by one member of the team at a time.
Why Kafka suits audit logging
Kafka has three natural strengths for this job. First, it is append-only: new events are added at the end of a partition, and the normal way of using it never rewrites earlier ones. Second, it is durable: events are saved to disk and copied to other brokers. Third, it is replayable: an investigator can start reading from any offset and re-live what happened. Those three traits are exactly what an audit trail needs.
They are not enough on their own, though. Append-only in normal use does not mean tamper-proof, and durable does not mean forever. The rest of this guide is about closing those gaps.
3Two Ways to Think About Audit Logging in Kafka
People use the phrase “audit logging in Kafka” to mean two related but different jobs. Mixing them up is the most common source of confusion, so let us separate them at the start.
Meaning one: auditing the Kafka platform itself
Here the question is: who did what to my Kafka cluster? Who connected? Who was refused permission? Who created a topic, deleted a topic, changed a retention setting or altered an access rule? Your platform team and your security team both care about this, because an attacker or a careless administrator with the wrong permissions can quietly damage the data of every application on the cluster.
Meaning two: using Kafka as the pipe for application audit events
Here the question is: how do I carry the audit events of my business applications safely? Your banking app, your hospital records system and your admin portal all generate audit events. Kafka becomes the reliable highway that collects them, fans them out to storage, search and alerting, and keeps a replayable copy.
Meaning one is like keeping a visitor book at the front gate of the post office: it records who entered the building and which rooms they opened. Meaning two is like using the post office to deliver the visitor books of every other building in town. Same building, two different jobs.
| Question | Platform auditing | Audit pipeline on Kafka |
|---|---|---|
| What is being recorded? | Logins, permission checks, admin changes on the cluster | Business actions from many applications |
| Who owns it? | Platform and security teams | Application teams plus compliance |
| Where do events start? | Inside the brokers and admin tools | Inside your services and databases |
| Typical risk | Silent tampering with the cluster | Lost or altered business audit events |
A serious compliance program needs both. If you only build the pipeline, an administrator could still delete your audit topic without leaving a trace. If you only audit the cluster, you have no organized way to collect the events from your applications. The chapters that follow cover each side and then join them together.
4The Compliance Rulebook in Simple Terms
You do not need to memorize legal text. You do need to know what each major rule pushes you to build. Please treat this chapter as a friendly map, not legal advice; always confirm the details with your compliance team or lawyers.
The main frameworks
| Framework | Who it covers | What it asks of audit logs |
|---|---|---|
| SOX (Sarbanes-Oxley) | Public companies in the United States | Trustworthy records of changes to financial systems, with strong access control and commonly about seven years of retention |
| PCI DSS | Anyone handling payment card data | Log access to card data and system components, protect the logs, keep at least 12 months with 3 months quickly available |
| HIPAA | US healthcare providers and their partners | Audit controls that record activity in systems holding patient information; related documentation kept for six years |
| GDPR | Anyone handling data of people in the European Union | Be able to demonstrate accountability and security, while also keeping personal data no longer than needed |
| SOC 2 | Service companies selling to businesses | Evidence that monitoring and access controls work over time |
| ISO 27001 | Any organization seeking certification | A defined logging control, with protected and reviewed logs |
Six ideas hiding behind all the rules
The frameworks use different words, but they keep asking for the same six qualities. Learn these and you can design for any of them.
Completeness
Every important action is recorded. A gap in the record looks the same as a cover-up.
Accuracy and time order
Timestamps are correct and events can be put in the right order.
Integrity
You can prove that records were not changed, deleted or slipped in afterwards.
Confidentiality
Only the right people can read the logs, and private data inside them is protected.
Retention
Records are kept for the required period, then disposed of properly.
Availability for review
When an auditor asks, you can find and produce the relevant records quickly.
Retention rules can pull in opposite directions. One rule says “keep it for years” while privacy law says “do not keep personal data longer than necessary”. Chapter 11 shows how to satisfy both at once.
Notice what these six qualities are about. None of them says “use Kafka”. They are goals. Kafka is a tool that can help you reach several of them, and the remaining chapters show which Kafka features serve which goal.
5Anatomy of a Good Audit Event
The quality of your audit trail is decided long before Kafka gets involved. It starts with what each single event contains.
Use one standard envelope
If every team invents its own audit format, investigators will spend their days translating. Instead, define one common envelope: a fixed set of fields that every audit event must carry, plus a flexible section for details that are specific to one application.
An envelope works like a shipping label. Every parcel in the world has the same label layout: sender, receiver, tracking number, date. What is inside the parcel can be anything, but the label lets any sorting machine handle it.
| Field group | Example contents | Why it matters |
|---|---|---|
| Identity of the event | Unique event id, schema version, event type | Lets you detect duplicates and understand old records years later |
| Actor | User id, service name, role, session id, on-behalf-of user | Answers “who” |
| Action | Verb such as create, update, delete, read, approve, login | Answers “what” |
| Target | Type and id of the record touched, plus before and after summaries where allowed | Answers “to what” |
| Time | Time the action happened, in UTC with millisecond precision | Answers “when” and supports ordering |
| Origin | Source system, host or container, client address, region | Answers “where” |
| Outcome | Success, failure or denied, with a reason code | Answers “did it work” |
| Correlation | Trace id or request id shared with application logs | Connects an audit record to the wider story |
Record the decision, not just the success
Failed and denied actions are often more interesting than successful ones. Ten failed logins followed by one success tells a very different story than one success alone. Always audit refusals, not just completions.
Time deserves extra care
Kafka stamps every record with a time, and it can do so in two ways. Create time is set by the producer, using the producer’s clock. Log append time is set by the broker at the moment it stores the record. A producer’s clock can be wrong, or even changed on purpose, so a careful design keeps both: the time the action happened as reported by the source, and the time Kafka received it. When the two differ wildly, that difference is a clue worth investigating.
Keep all machines synchronized with a trusted time service, and store times in one zone (UTC) so nobody has to guess about daylight saving changes.
Lock the format with a schema
A schema is a written contract describing exactly which fields an event has and what type each field is. Tools such as a Schema Registry, used with formats like Avro or Protobuf, refuse events that break the contract and control how the contract may evolve. For audit data this is a gift: it prevents a well-meaning developer from renaming or dropping a field that an auditor relies on.
Choose compatibility rules that only allow adding optional fields. Old audit records must stay readable for the whole retention period, which might be a decade.
Choose the message key wisely
In Kafka, the key of a message decides which partition it goes to, and Kafka only promises ordering within one partition. If you key audit events by the id of the thing being changed, such as the account number, then every event about that account lands in the same partition, in the right order. That makes “show me the full history of this account” a straightforward read.
6The Big Picture Architecture
Now let us zoom out and see all the pieces of a complete audit pipeline, from the moment an action happens to the moment an auditor reads the record.
flowchart LR
A["Applications and Services"] --> B["Audit Producer Library"]
K["Kafka Cluster Security Events"] --> C
B --> C["Kafka Audit Topics"]
C --> D["Stream Processor for Enrichment"]
D --> E["Kafka Connect Sink"]
E --> F["Immutable Archive with Object Lock"]
C --> G["Search Index for Investigators"]
C --> H["Alerting and SIEM"]
Walking through the diagram
Applications and services are where actions happen. They do not write directly to Kafka in a haphazard way. They use a shared audit producer library, a small piece of code every team includes, which builds the standard envelope from Chapter 5, adds identity and time, and sends the event. One library means one place to fix bugs and one consistent format.
The Kafka audit topics are the heart of the design. Events are collected here, copied across brokers, and held for a defined period. The Kafka cluster security events box on the left shows that the platform’s own login and permission records feed into the same stream, so investigators see both stories together.
A stream processor reads the raw events and enriches them. For example, it may attach the department of a user, translate an internal id into a readable name, or mask a sensitive value. Then a Kafka Connect sink, a ready-made tool for moving data out of Kafka, writes the events to an immutable archive such as object storage with write-once protection. Two other consumers read the same topics independently: a search index so investigators can query quickly, and an alerting system that raises the alarm on suspicious patterns.
Think of a newsroom. Reporters (applications) file stories through a standard form (the producer library). The news wire (Kafka) distributes each story to the archive room, the search desk and the breaking-news desk at the same time, and none of them has to slow the others down.
Why several independent consumers matter
Kafka lets many consumer groups read the same topic without interfering. This is a big advantage for compliance. The archive can be slow and careful, the search index can be fast and disposable, and the alerting tool can be picky, all from one source of truth. If the search index is ever corrupted, you rebuild it by replaying the topic. The audit records themselves stay safe.
7Auditing the Kafka Cluster Itself
Now we turn to the first meaning from Chapter 3: recording what happens on the cluster. This is where Kafka’s built-in abilities and your own additions come together.
Step one: know who is connecting (authentication)
Authentication means proving who you are. Kafka can ask clients to prove identity with certificates (mutual TLS), with usernames and passwords in a safer challenge form (SASL SCRAM), with Kerberos, or with tokens (OAuth bearer). For audit purposes the vital point is that every client must have its own identity. If ten applications share one login, the log can say only “the shared login did it”, and that is useless to an investigator.
Step two: control what they can do (authorization)
Authorization means deciding what an identity is allowed to do. Kafka uses access control lists, usually shortened to ACLs. Each rule says that a certain identity may or may not perform a certain operation, such as read, write, create or delete, on a certain resource, such as a topic, a consumer group or the cluster as a whole.
Step three: record every decision
Kafka brokers include an authorizer log. By default it records requests that were denied. If you raise its detail level, it records allowed requests as well, at the price of much larger log volume. Brokers also have a request log that shows every call clients make, but it is extremely detailed and normally switched on only briefly when troubleshooting, not as a permanent audit feed.
sequenceDiagram
participant C as Client App
participant B as Kafka Broker
participant A as Authorizer
participant L as Audit Log
C->>B: Connect with credentials
B->>B: Verify identity
B->>L: Record login success or failure
C->>B: Request to write to a topic
B->>A: Is this identity allowed
A-->>B: Allowed or denied
B->>L: Record the decision
B-->>C: Send result to client
Read the diagram from top to bottom. The client connects and the broker checks who it is, writing down the result. Then the client asks to do something. The broker asks the authorizer whether that identity may do it, and writes down the answer before replying. Two records, two moments, one complete story.
What the built-in logs do not give you
Plain Apache Kafka writes these records into ordinary broker log files, in a text format meant for humans. That is a fine start but it falls short of compliance needs in three ways. The files sit on the same machines an attacker may control. The format is not a tidy structured event. And an administrator with shell access could edit them. So the usual practice is to ship these files off the broker immediately with a log shipper into a protected, separate system, and to turn them into structured events.
Some commercial Kafka distributions add a ready-made feature here. Confluent, for instance, offers audit logs for its platform and cloud service that write structured records, in a standard event format, into a dedicated Kafka topic. Managed services help in other ways: Amazon MSK can deliver broker logs to CloudWatch Logs, S3 or Firehose, and AWS CloudTrail records the management calls made to the MSK service itself, such as creating or deleting a cluster.
Cloud audit tools like CloudTrail see the control plane, meaning the actions on the cluster as a resource. They do not see the data plane, meaning which application read which topic. You still need Kafka’s own authorization records for that.
The administrative actions you must never miss
- Creating, deleting or changing a topic, including changes to its retention time.
- Adding, removing or altering an ACL.
- Using the delete-records operation, which removes old data from a partition.
- Changing broker or cluster configuration.
- Creating or removing credentials and tokens.
Each of these could quietly destroy or expose audit data. Treat them as high-severity events and alert on them.
8Getting Audit Events Into Kafka Reliably
Here is a truth that surprises many teams: the hardest part is not storing audit events in Kafka. It is making sure that every event that should be stored actually gets there.
The dual-write trap
Imagine a service that updates a customer’s address in its database and then sends an audit event to Kafka. That is two separate systems and two separate steps. If the database update succeeds but the service crashes before sending the event, you have a change with no audit record. If the event is sent but the database update then fails, you have an audit record of something that never happened. Both are compliance failures, and both are invisible until an auditor looks.
It is like a cashier who takes your money in one room and prints your receipt in another. If the power fails between rooms, you have paid with no receipt, or a receipt without payment. The fix is to make the receipt part of the same act as the payment.
The transactional outbox pattern
The standard cure is the outbox pattern. The service writes the business change and the audit event into the same database, inside one transaction. The audit event goes into a special table, the outbox. Either both are saved or neither is. A separate relay process then reads new rows from the outbox and publishes them to Kafka. Some teams do the relay by watching the database’s own change log, using a tool such as Debezium.
sequenceDiagram
participant S as Service
participant D as Database
participant R as Outbox Relay
participant K as Kafka
S->>D: Begin transaction
S->>D: Save the business change
S->>D: Save the audit event in the outbox table
S->>D: Commit both together
R->>D: Read new outbox rows
R->>K: Publish audit event and wait for acknowledgement
K-->>R: Acknowledged by in-sync replicas
R->>D: Mark row as published
If the relay crashes between publishing and marking the row, it may publish the same event twice. That is acceptable, because each event carries a unique id and consumers can spot and ignore duplicates. It is far better to have a harmless duplicate than a missing record.
Producer settings that protect you
When the relay or an application sends events, a few Kafka producer settings decide how safe the send is.
| Setting idea | Plain meaning | Audit choice |
|---|---|---|
| Acknowledgements | How many copies must confirm before the producer is told “done” | Require all in-sync replicas (acks=all) |
| Idempotence | Kafka removes duplicates caused by retries | Keep it on; it is the default in modern versions |
| Retries | How persistently the producer resends after a hiccup | Generous, with a long delivery timeout |
| Ordering under retry | Whether a retry can reorder events | Keep the in-flight limit safe so order per key holds |
What if Kafka is down?
An audit design must decide, in advance, what happens when Kafka cannot be reached. There are two honest choices. Fail closed means the business action is refused if it cannot be audited. Banks often choose this for sensitive operations such as moving money. Buffer and continue means the outbox keeps the events safely in the database until Kafka returns. With the outbox pattern you get the second choice almost for free, because the events are already saved. Whichever you pick, write it down and test it. Auditors love a documented and rehearsed failure plan.
Kafka transactions give exactly-once guarantees between Kafka topics. They do not span your database. For the database-to-Kafka hop, the outbox pattern is the tool to reach for.
9Keeping the Trail Durable and Available
An audit record that disappears when a server breaks is worthless. Kafka gives you strong tools to survive machine failures, but only if you set them up on purpose.
Replication: many copies, no single point of failure
Each partition has one leader copy that handles reads and writes, and several follower copies on other brokers that stay in step with it. The followers that are fully caught up form the in-sync replica set. A common production layout keeps three copies, each in a different data center zone.
flowchart LR
P["Producer"] --> L["Leader copy in Zone 1"]
L --> F1["Follower copy in Zone 2"]
L --> F2["Follower copy in Zone 3"]
F1 --> ACK["Acknowledgement to producer"]
F2 --> ACK
ACK --> P
Think of three notaries in three different cities each holding an identical copy of an important contract. A fire in one city destroys one copy, but the contract still exists, and any notary can produce it.
Three settings that work as a team
- Replication factor of three means three copies exist.
- Minimum in-sync replicas of two (
min.insync.replicas) means a write is only accepted if at least two copies can confirm it. - Producer acknowledgement set to all means the producer waits for those confirmations.
Together they mean that when an audit event is acknowledged, it exists on at least two machines. You can lose one machine at any moment and lose nothing. Also switch off unclean leader election. That setting would let an out-of-date copy become the leader in an emergency, silently discarding events it never received. For audit data, availability is not worth that price.
Retention: how long Kafka keeps events
Every topic has a retention rule, by time or by size, after which old segments are deleted. Audit topics usually need a long time setting, and Kafka allows unlimited retention if you choose it. Two cautions apply here.
Never use log compaction on an audit topic. Compaction keeps only the latest record for each key and throws away the older ones. That is perfect for “current address of customer 42” and disastrous for “everything that ever happened to customer 42”.
Second, long retention on broker disks is costly. Newer Kafka versions support tiered storage, which keeps recent data on fast local disks and moves older data to cheap object storage while still letting consumers read it through Kafka. That allows months of replayable history without paying for enormous broker disks.
Surviving a whole region going dark
Replication across zones protects against a building failing. A regional disaster needs a second cluster in another region, kept in step by a mirroring tool such as MirrorMaker 2, which copies topics between clusters. Because mirroring is not instant, plan for a small gap and combine it with the archive in Chapter 13, which is independent of any cluster.
10Making the Trail Tamper-Evident
Auditors do not only ask whether you have logs. They ask whether you can prove nobody changed them. This chapter is about turning “trust us” into “verify it yourself”.
Kafka is append-only, but not tamper-proof
In normal use, Kafka never edits a stored record. But that is a habit of the software, not a law of nature. A user with powerful enough permissions can delete a topic, shorten its retention so the data expires, call the delete-records operation, or even edit files directly on a broker’s disk. Kafka on its own is therefore append-only but not immutable. Compliance needs the second word.
Idea one: hash chaining
A hash is a fingerprint computed from data. Change one letter of the data and the fingerprint changes completely. In a hash chain, each audit event includes the fingerprint of the previous event. To rewrite history, an attacker would have to recompute every fingerprint after the change, and every checkpoint that was already published elsewhere.
flowchart LR
E1["Event 1 with hash H1"] --> E2["Event 2 stores H1 and has hash H2"]
E2 --> E3["Event 3 stores H2 and has hash H3"]
E3 --> S["Periodic signed checkpoint"]
S --> V["Verifier recomputes the chain"]
Imagine a notebook where every page begins by copying the last line of the previous page. If someone rips out or rewrites a page in the middle, the copied lines no longer match and the tampering shows immediately.
Idea two: digital signatures on checkpoints
Chains alone can be rebuilt by someone with enough access. So every so often, a separate trusted component takes the latest fingerprint and digitally signs it with a private key held in a protected key service such as a hardware security module or a cloud key management service. The signed checkpoint is stored somewhere the Kafka administrators cannot touch. A verifier can later recompute the chain and check it against the signed checkpoints. AWS CloudTrail uses the same idea with its log file integrity validation, which relies on hashing and digital signing so you can detect changes to delivered log files.
Idea three: write once, read many storage
The strongest protection is to copy audit events to storage that physically refuses changes. Object storage such as Amazon S3 offers Object Lock. In its compliance mode, nobody, not even the account owner, can delete or overwrite a locked object until its retention date passes. AWS describes this as designed to help meet write-once-read-many requirements, such as those in financial record-keeping rules. A lock on the archive means that even if an intruder gains full control of Kafka, the archived copy survives.
Idea four: audit the auditors
Who can change the audit topic’s settings? Who can change the signing keys? Every one of those actions must itself be logged, and the log of those actions must be stored where the same people cannot alter it. This is called meta-auditing, and auditors look for it specifically.
Use a separate cloud account, or at least a separate set of credentials, for the archive and the signing keys. If the same administrators control both Kafka and the vault, the vault adds little protection.
11Protecting Sensitive Data Inside Audit Records
Audit logs have an awkward nature: they are a concentrated record of everything sensitive that happened, so they are a juicy target. Protecting them is part of the job.
Log the fact, not the secret
The first rule is to record what happened without copying the private details. “User changed their password” is an audit fact. The password itself must never appear, not even hashed. Likewise, do not write full card numbers, medical notes or government identification numbers into audit events. Store an identifier, a masked form such as the last four digits, or a token that points to the real value in a protected system.
Encrypt everything, everywhere
- In transit: use TLS between clients and brokers, and between brokers.
- At rest: encrypt broker disks and archive storage with keys you control.
- Field level: for especially sensitive fields, encrypt just that field inside the event, so that only a small group holding the key can read it while everyone else still sees the rest of the record.
The privacy paradox and crypto-shredding
Privacy laws such as GDPR give people the right to have personal data erased in many situations, though there are exceptions, including where the law requires you to keep records. Audit logs are meant to be permanent and unchangeable. These two ideas seem to collide. You cannot edit a locked archive to remove one person’s name.
A clever, widely used answer is crypto-shredding. Each person’s personal fields are encrypted with a key made just for that person, and the keys live in a key service. To “erase” the person, you delete their key. The encrypted words remain in the archive, but they are now unreadable forever, while the rest of the audit trail, who acted and when, stays intact.
Suppose every person’s diary entries are written in a private code, and the code book is kept in a separate safe. Burning that person’s code book leaves the diary pages on the shelf, but no one can ever read them again.
Talk to your legal team before designing erasure behavior. Whether crypto-shredding is enough, and which data you must keep, depends on the law and the situation. Design the technical option early, so that lawyers have a choice to make.
Keep secrets out of the plumbing
Do not put access tokens, session cookies or passwords in message headers or keys. Keys and headers are often copied into monitoring tools and are easy to leak. Also review what your stream processor and search index store, because every copy of an audit event is another place that needs protection.
12Locking Down Who Can Touch the Audit Topics
A perfect design can be undone by a single overly generous permission. Access control on the audit topics deserves the same care you give to the vault of a bank.
Least privilege and separation of duties
Least privilege means every identity gets only the permissions it truly needs and nothing more. Separation of duties means no single person can both do something risky and hide the evidence of it. Together they are the backbone of SOX-style controls.
| Who | May write | May read | May change topic settings or delete |
|---|---|---|---|
| Application services | Yes, to the audit topic only | No | No |
| Outbox relay | Yes | No | No |
| Archive and index connectors | No | Yes | No |
| Security and compliance analysts | No | Yes, through the search tool | No |
| Platform administrators | No | Limited | Only through an approved, logged, time-limited process |
Practical rules
Write-only producers
A service that produces audit events should not be able to read other services’ audit events.
No wildcards
Avoid ACLs that match every topic. Name the audit topics explicitly, or use a tightly scoped prefix.
Break-glass access
Powerful admin rights are granted for a short time, with approval, and every use is logged and reviewed.
Individual identities
One identity per person and per service. Shared accounts destroy accountability.
Regular review
Every quarter, list who holds access and remove anything no longer needed. Keep evidence of the review.
Protect the ACLs
Changing an ACL is an audited, high-severity event and should trigger an alert.
Store your ACLs as reviewed configuration files in version control, and apply them by automation. Then every permission change has an author, a reviewer and a timestamp for free.
13Retention, Archival and Retrieval
Keeping records for seven years is one thing. Being able to find one specific record inside those seven years, on a deadline, is another.
Think in temperature: hot, warm and cold
Not all audit data is needed equally fast. Recent events are searched often; old ones rarely. Storing everything on the fastest, most expensive system would waste money, and storing everything in the cheapest would frustrate investigators. Tiering solves it.
flowchart TD
A["Hot tier: Kafka brokers, days to weeks"] --> B["Warm tier: tiered storage or search index, months"]
B --> C["Cold tier: locked object archive, years"]
C --> D["Legal hold or disposal review"]
| Tier | Where it lives | Typical age | How it is used |
|---|---|---|---|
| Hot | Kafka brokers | Days to a few weeks | Live alerting, replay, stream processing |
| Warm | Search index or tiered storage | A few months | Fast investigations and routine audit requests |
| Cold | Locked object storage in a columnar file format | Up to the full legal period | Formal audits, legal cases, rare lookups |
Make the archive searchable
Write archived events in an efficient file format, partitioned by date and, if useful, by event type. Then a query service can scan only the small slice needed. Query engines that read directly from object storage, such as Amazon Athena, make it possible to answer “show all deletions by this user in March” without loading anything back into Kafka.
Legal holds and disposal
When a lawsuit or investigation begins, a legal hold freezes the relevant records so they cannot be deleted even when their normal retention ends. Object Lock supports legal holds for exactly this. When the retention period does pass and no hold applies, disposal should also be deliberate, logged and, where required, approved. Keeping data forever “just in case” can itself be a compliance failure, as privacy rules expect you not to hoard personal data.
Rehearse the retrieval
Do a drill. Pick a random event from two years ago and time how long it takes your team to produce it, prove its integrity and hand it over. If the answer is “a week and three engineers”, fix that before an auditor finds out.
14Kafka Connect and Schema Evolution for the Archive
The bridge between Kafka and your long-term archive is easy to overlook, yet it is the piece that decides whether your records are still readable in ten years.
What Kafka Connect does
Kafka Connect is a framework for moving data into and out of Kafka without writing custom code. You configure a connector, which is a ready-made plug for a specific system. A source connector pulls data into Kafka, for example from a database change log. A sink connector pushes data out of Kafka, for example into object storage. Connect runs the connector as a set of tasks spread across worker machines, restarts them if they fail and remembers how far each has read.
Connect is like a fleet of trained couriers. You tell them which shelf to collect from and which warehouse to deliver to. They split the work, keep a checklist of what they delivered, and if one gets sick, another continues from the checklist.
Choices that matter for audit data
- File format. Column-oriented formats such as Parquet compress well and speed up queries. Row-oriented formats such as Avro keep every field of an event together, which suits full-record retrieval. Many teams keep one of each.
- Partitioning by time. Writing files into folders by date and hour makes searches cheap, and it makes output deterministic, meaning the same events always land in the same files.
- Delivery guarantee. Some sink connectors can offer exactly-once delivery when configured with a deterministic, time-based layout. Otherwise expect at-least-once, and rely on the unique event id to remove duplicates.
- File size and rotation. Too many tiny files slow every query. Rotate files by size or time so that each holds a healthy amount of data.
- Manifests and checksums. Record the name and fingerprint of every archived file. A manifest makes integrity verification and legal exports far easier.
Handling bad records without losing them
Sooner or later a malformed event will appear. The connector can be told to stop the entire pipeline, to skip the bad record, or to send it to a dead-letter topic for humans to inspect. For audit data, skipping silently is the worst option, because a skipped record is a lost record. Prefer the dead-letter topic, alert on anything that lands there, and treat the queue as a to-do list that must be emptied.
| Problem | Wrong reaction | Right reaction |
|---|---|---|
| Record fails schema check | Drop it and carry on | Send to a dead-letter topic, alert, fix and replay |
| Archive storage unreachable | Skip the batch | Retry, let lag grow, alert on lag, keep data in Kafka |
| Connector crashes mid-batch | Restart from the newest offset | Restart from the last saved offset and deduplicate by event id |
| Field renamed by a developer | Accept it quietly | Block it through compatibility rules in the schema registry |
Schema evolution without regret
Your event format will change over the years: new fields, new event types, new regulations. A schema registry can enforce compatibility. In backward compatible mode, readers using the new schema can still read old data. In forward compatible mode, readers using an old schema can still read new data. Full compatibility means both. For audit data, the safest habit is simple: only add optional fields with default values, never remove or rename a field, and never reuse a field name for a different meaning.
Now for the trick that people forget. Store the schema together with the data. Avro files carry their schema inside. For other formats, save the schema versions in the archive alongside the events. Ten years from now, your schema registry product may have changed, or the server may be gone, but an archive that explains itself will still be readable.
Once a year, pick an archived file from your oldest year and read it using only the documentation and tools you have today. If that works smoothly, your archive is truly future-proof.
15Multiple Regions and Data Residency
Large companies operate in many countries, and many countries have rules about where personal data may live. Audit logs are full of personal identifiers, so those rules apply to them too.
Why location matters
Privacy regulations often restrict moving personal data across borders, and some countries require certain data to stay inside their territory. An audit event that says “employee Maria in Berlin viewed the record of customer 8841” contains personal data about at least two people. If you ship every event from every country into one central cluster, you may create a legal problem while solving a technical one.
Think of a company with branch offices in several countries. Each branch keeps its own filing cabinet on site, following local law. Headquarters receives summary reports, not the raw files of every branch.
Three ways to organize it
| Approach | How it works | Strengths | Weaknesses |
|---|---|---|---|
| One global cluster | All events flow into a single place | Simple; one search | May break residency rules; long network distances |
| Regional clusters and archives | Each region keeps its own audit data in its own jurisdiction | Respects local law; fast local writes | Cross-region investigations are harder |
| Regional plus pseudonymized summary | Regions keep full data; a reduced copy with personal fields replaced by tokens goes to a central view | Global visibility and local compliance | More design work; token vaults must be protected |
Practical guidance
- Keep keys local. Use encryption keys held in the same region as the data. Crypto-shredding then works inside the jurisdiction.
- Disaster recovery inside the boundary. If your data must stay in the European Union, put the backup region in the European Union as well.
- Search where the data lives. A central security team can send its queries to each region and receive only the answers it needs, rather than copying everything to one place.
- Do not promise one global order. Clocks in different regions differ slightly, and events from separate clusters have no shared sequence. Order events within each region by sequence numbers and treat cross-region timing as approximate, showing both source times and arrival times.
- Avoid synchronous cross-region writes. Waiting for a distant region to confirm every audit event makes the business slow. Write locally, copy onwards in the background.
Mirroring tools copy records exactly, including any personal data inside them. Before you mirror a topic between regions, confirm with your legal team that the transfer is allowed, or mirror only the pseudonymized version.
16Inside the Broker: How an Audit Event Is Stored Safely
To trust Kafka with evidence, it helps to know what actually happens between “the producer sent it” and “it is safe”. The story is simpler than you might fear.
Step by step through a single write
When a producer sends audit events, it does not send them one at a time. It gathers several into a batch for the same partition, often compresses the batch to save space, and sends it to that partition’s leader broker. The leader appends the batch to the end of the partition’s current log segment, which is simply a file on disk. Segments have a maximum size, and when one fills up, Kafka starts a new one. Deleting old data means deleting whole segment files, which is why retention is quick and cheap.
Next, the follower brokers, which hold the other copies, continuously ask the leader for new data. This is a pull design: followers fetch, the leader does not push. As followers confirm they have the data, the leader advances a marker called the high watermark. This marker is the highest offset that every in-sync copy has stored. Consumers can only read up to the high watermark, so they never see an event that could still be lost in a failover.
sequenceDiagram
participant P as Producer
participant L as Leader Broker
participant F1 as Follower One
participant F2 as Follower Two
participant C as Consumer
P->>L: Send batch of audit events
L->>L: Append to log segment
F1->>L: Fetch new data
F2->>L: Fetch new data
L->>L: Advance high watermark
L-->>P: Acknowledge with all in-sync copies
C->>L: Read up to high watermark
Imagine a court reporter typing a transcript while two assistants each make their own copy. The transcript is only “official” up to the last line that both assistants have copied. If the reporter’s typewriter breaks, nothing official is lost.
Does Kafka write to disk instantly?
This surprises many people. By default, Kafka hands data to the operating system, which keeps it in memory and writes it to disk shortly after, rather than forcing a disk flush for every message. Kafka’s design relies on replication for safety, not on flushing a single machine’s disk each time. That is why the settings from Chapter 9 matter so much: with three copies in three zones and a minimum of two confirmations, the chance that all copies lose the same event at once is tiny. Forcing constant flushes would cost a lot of speed for little extra safety.
Who manages the cluster?
Someone must decide which broker leads which partition and what to do when a broker dies. In modern Kafka this is handled by a group of controller nodes running Kafka’s own consensus protocol, called KRaft. Older clusters used a separate coordination system called ZooKeeper. For audit purposes, remember that the controllers hold the cluster’s metadata, including ACLs, so they deserve the same protection as brokers, and changes to them should also be audited.
Where do reader positions live?
A consumer group remembers how far it has read by saving its offset in an internal Kafka topic. The safest habit for an archive connector is to save its position only after the data has been written to the archive successfully. If the connector crashes mid-way, it will re-read a few events and write them again. This is called at-least-once delivery. Combined with unique event ids, a duplicate is harmless, but a missing event is not, so at-least-once is the right side to err on.
Tell Kafka which zone each broker lives in using rack awareness. Then it spreads the copies of each partition across different zones automatically, instead of accidentally placing all three copies in one building.
17The Life of One Audit Event
Let us follow a single event, from the moment someone clicks a button to the day it is finally retired. Seeing the whole journey makes it clear where each control fits.
The action happens
A finance manager approves a supplier payment. The service checks her permissions and performs the approval.
The envelope is built
The shared library fills in actor, action, target, time, origin and outcome, adds a unique event id and a trace id, masks sensitive values and encrypts what must be kept.
The event is committed with the change
The approval and the audit event are saved in one database transaction. From this moment the event cannot be lost, even if the service crashes.
The relay publishes it
The relay sends the event to the audit topic. The schema registry confirms the format is valid. Kafka replicates and acknowledges it.
Readers pick it up
The stream processor enriches it, the search index makes it findable, the alerting engine checks it against rules, and the archive connector queues it for storage.
It is chained and archived
The event joins the hash chain. The archive connector writes it into a locked object store. A signed checkpoint covers it soon after.
It is verified regularly
A scheduled verifier recomputes the chain and compares it with the signed checkpoints. Reconciliation confirms the counts match at every stage.
It ages through the tiers
After some weeks it leaves the brokers, after some months it leaves the search index, and it rests in the archive for the remaining years.
It is disposed of, or held
At the end of the retention period, the event is deleted in a logged and approved way, unless a legal hold keeps it alive.
What can go wrong at each step
| Stage | Failure to expect | Control that catches it |
|---|---|---|
| Build | Missing or wrong fields | Shared library and schema validation |
| Commit | Crash between change and event | Outbox in the same transaction |
| Publish | Kafka temporarily down | Outbox buffering and retries |
| Replicate | Broker or zone failure | Three copies, minimum two in sync |
| Consume | Connector stuck or crashing | Lag alerts and at-least-once reading |
| Archive | Silent write failure | Count reconciliation |
| Retain | Premature deletion or tampering | Object Lock, signatures, meta-audit |
It is like a passport application moving through an embassy. It is stamped when submitted, copied, checked by more than one desk, filed in a locked cabinet and finally shredded after a set number of years, with a log of every hand it passed through.
18Kafka Security Layers in Depth
Chapter 7 touched on authentication and authorization. Here we build the full picture, layer by layer, because audit data is only as safe as the weakest layer around it.
A castle does not rely on one wall. It has a moat, a gate, guards who check names, locked rooms and a treasurer who only opens the vault for approved people. Kafka security is layered the same way.
Layer 1: the network
Brokers should live in private network segments with no public address. Firewall rules or cloud security groups allow only known clients, known administrators and other brokers to reach them. This reduces who can even attempt to connect, which shrinks the number of events your audit log must explain.
Layer 2: encryption in transit
TLS scrambles traffic so that anyone listening on the network sees only noise. Turn it on for client-to-broker traffic and for broker-to-broker traffic. Rotate certificates before they expire, and treat an expired certificate as an outage-in-waiting, because a broken audit path is a compliance incident.
Layer 3: proving identity
Choose one strong method and use it consistently. Mutual TLS gives each client a certificate. SASL with SCRAM gives each client a salted, challenge-protected password. OAuth tokens let you plug into a company identity provider so that people and services come from a central directory. Kerberos is common in older enterprises. Whatever you pick, the identity name that Kafka sees becomes the principal written into every authorization record, so name them meaningfully, such as the service name and environment.
Layer 4: permissions
ACLs bind principals to operations on resources. A few subtleties matter for audit work:
- Super users are principals that bypass ACL checks entirely. Keep that list very short, and alert whenever it changes.
- Denials override allows, which is useful for placing a hard block on a sensitive topic.
- Consumer groups are resources too. Without controlling them, a reader could join with an unexpected group name.
- Prefixed rules make it easy to protect every topic starting with an audit prefix, but a careless prefix can match more than you intend, so test it.
Layer 5: quotas
Quotas limit how much traffic a client may send or read. They protect the audit topic from a buggy service that suddenly floods it, which could push out other producers or fill disks. A quota breach is also a useful alert signal, since a service suddenly shouting is often either a bug or an attack.
Layer 6: the surrounding services
Kafka rarely runs alone. Kafka Connect exposes a web management interface that can start, stop and reconfigure connectors, so it must require authentication and be reachable only from trusted networks. The same goes for the schema registry, monitoring dashboards and any tool that can read audit topics. Attackers love the forgotten side door more than the main gate.
Layer 7: secrets and keys
Passwords, certificates and encryption keys belong in a secrets manager, never in configuration files stored in plain view or in shared chat channels. Rotate them on a schedule and log every read of a key.
Security tools that read audit topics are themselves clients with credentials. If their access is broader than needed, a compromise there exposes every audit event at once. Give them read-only access to only the topics they need.
19Performance, Sizing and Scale
Audit logging must never become the reason a payment is slow or a disk is full. A little arithmetic up front prevents nasty surprises later.
Do the storage math first
Suppose your systems produce 5,000 audit events every second, and the average event is about one kilobyte. That is roughly five megabytes per second, or about 430 gigabytes per day before compression. Audit events are text-like and repetitive, so compression often shrinks them several times over; assume roughly 100 gigabytes per day after compression as a planning figure. With three copies, that becomes about 300 gigabytes of broker disk per day. Keep 90 days on the brokers and you need around 27 terabytes. These are illustrative numbers, not a promise for your data, but the pattern is clear: broker retention gets expensive fast, which is why the tiers of Chapter 13 exist.
Choose partitions with care
More partitions mean more parallel writers and readers. But there is a catch specific to audit data. If you increase the number of partitions later, the mapping from key to partition changes, so new events for an account may land in a different partition than its old ones, which weakens the per-account ordering you designed. It is also impossible to reduce partitions. So estimate growth generously and start with more partitions than you need today. A modest surplus costs little, while a redesign is painful.
Batching and compression
Producers can wait a few milliseconds to fill larger batches, which raises throughput and cuts network use. Audit pipelines are rarely latency-sensitive in the millisecond sense, since an auditor does not care whether an event arrived in 5 or 50 milliseconds. So lean toward larger batches and efficient compression. Just keep the delay small enough that alerts on dangerous actions still fire quickly.
A delivery truck that leaves the depot with one parcel at a time wastes fuel. Waiting a few minutes to fill the truck moves many more parcels per trip, and the customers barely notice the difference.
Do not let the audit path block the business
With the outbox pattern, the only cost the application pays is one extra small row written inside a transaction it was already making. The relay, Kafka and every downstream reader work in the background. If a reader slows down, the business flow does not.
Plan for peaks
Audit traffic follows business traffic. A shopping site sees spikes on sale days; a bank sees them at month end. Size for the peak, keep spare disk headroom, and load-test with realistic bursts. Watch consumer lag during tests, because that is where an undersized archive connector reveals itself.
Use separate topics, or at least separate quotas, for high-volume low-value events (such as every page view) and low-volume high-value events (such as permission changes). That way the noisy stream can never drown the important one.
20Building It on AWS with Amazon MSK
Many teams run Kafka on Amazon Managed Streaming for Apache Kafka, known as MSK. It removes much of the machine-level work and pairs nicely with other AWS services that solve the compliance puzzle.
flowchart LR
subgraph W["Workload account"]
S["Application services"] --> M["Amazon MSK across three zones"]
M --> C["MSK Connect S3 sink"]
end
subgraph A["Audit account"]
B["S3 bucket with Object Lock"]
K["KMS keys for encryption and signing"]
Q["Athena for investigator queries"]
end
C --> B
K --> B
B --> Q
The pieces and their jobs
Amazon MSK
Runs brokers across three zones. Supports TLS, IAM-based access control, SASL/SCRAM and mutual TLS, plus encryption at rest with KMS keys.
MSK Connect
Runs Kafka Connect for you. An S3 sink connector copies audit topics into object storage in date-partitioned files.
S3 with Object Lock
The write-once archive. Compliance mode and legal holds protect records from deletion until their time is up.
AWS KMS
Holds encryption keys and signing keys. Key use is itself logged, giving you evidence about who touched keys.
AWS CloudTrail
Logs control-plane calls, such as someone changing an MSK cluster or a bucket policy, into its own protected trail.
CloudWatch
Metrics and alarms on broker health, lag and connector status. MSK can also send broker logs to CloudWatch Logs, S3 or Firehose.
Athena and OpenSearch
Athena queries the archive in place; OpenSearch provides a fast index for recent events.
Separate accounts
The audit account is owned by security, not by the teams whose actions are being recorded.
Why two accounts
The most valuable design choice in the diagram is the boundary between the workload account and the audit account. Engineers who run the applications and even the Kafka cluster can send data into the audit bucket, but they cannot delete it, change its lock, or use the signing keys. Only a small security group controls the audit account. This is separation of duties made physical.
It is like a company that keeps its accounting books at an outside audit firm. The staff can hand over receipts through a mail slot, but they cannot walk in and change last year’s ledger.
Points to remember
- Use a bucket policy that allows only the connector’s role to add objects, and denies delete operations to everyone.
- Enable versioning and Object Lock when the bucket is created; the lock setting is a deliberate, planned decision.
- Choose the retention period from the longest applicable rule, and apply legal holds when needed.
- Turn on CloudTrail data events for the audit bucket, so that every access to it is recorded.
- Encrypt with keys whose policies are managed by the security team.
Compliance mode locks cannot be shortened, even by the account owner. Test your settings on a throwaway bucket first, because a mistake there is permanent and you would be paying to store the data until the date runs out.
21Investigating an Incident: A Full Walkthrough
A design proves its worth when something goes wrong. Here is an illustrative story that shows every layer helping.
The situation
On Monday morning, the finance team notices that the bank details of a supplier were changed last Friday night, and a large payment was then sent to the new account. Nobody remembers making the change. The security team opens an investigation.
Find the change
An investigator searches the index for the supplier’s account key. Because events were keyed by account, the whole history comes back in order: the bank detail update, the approval and the payment.
Identify the actor
The update was made by a real employee’s identity, from a client address in an unusual country, at 11:42 p.m. The record also shows a trace id.
Look at the surroundings
Using the trace id and the identity, the investigator finds five failed logins minutes earlier and a password reset just before the successful one. The pattern suggests a stolen account, not a dishonest employee.
Check the platform side
The cluster’s security events show whether the same principal touched anything else, and whether any audit topic settings or ACLs were changed. In this story they were not.
Prove the records are genuine
The verifier recomputes the chain across Friday and Saturday and confirms it matches the signed checkpoints. The archive copy is identical to the search index copy.
Contain and report
The account is disabled, the payment is recalled, and the security team exports an evidence package: the events, the verification results and the access records. Regulators and insurers receive it without any scramble.
What made this possible
Notice that no step required luck. Events were ordered because of the key choice in Chapter 5. Nothing was missing because of the outbox and reconciliation. The evidence was trusted because of the locked archive and signatures. And the story about the stolen account was clear because failed and denied actions had been recorded, not just the successes.
22Testing and Audit Readiness
Controls that are never tested tend to fail on the day they are needed. This chapter shows how to test your audit trail and how to be ready for the auditor’s visit.
Four kinds of testing
Contract tests
Every service’s audit events are checked automatically against the schema and against a list of required fields before the code is released.
Failure injection
In a test environment, stop a broker, cut a zone, pause a connector or break the network, then confirm that nothing was lost once things recover.
Tamper drills
Deliberately alter a copy of an archived record and confirm the verifier raises the alarm. A smoke detector needs occasional smoke.
Restore drills
Rebuild the search index from the archive or from a topic replay, and time how long it takes.
Map every requirement to a control and to evidence
Auditors think in three columns: what is required, what control you have, and what proof you can show. Build that table yourself, before they ask.
| Requirement | Control | Evidence you can show |
|---|---|---|
| Record access to sensitive data | Audit events for reads and changes with the standard envelope | Sample events, schema, coverage list of systems |
| Protect logs from change | Object Lock, signed checkpoints, ACL restrictions | Bucket settings, verifier reports, ACL files in version control |
| Retain for the required period | Retention policy on tiers and archive lock dates | Configuration exports and lifecycle rules |
| Limit who can read logs | Least-privilege ACLs and quarterly reviews | Review records signed by the data owner |
| Detect gaps and failures | Reconciliation, lag alerts and heartbeats | Alert history and incident tickets |
| Respond to erasure requests | Per-person keys and key deletion process | Key deletion logs and procedure documents |
Keep the evidence fresh
Screenshots taken once a year age badly. Automate the collection: configuration exports on a schedule, verifier results stored automatically, access review sign-offs recorded in a ticket system. When the auditor arrives, your job becomes handing over a folder rather than scrambling for screenshots.
A restaurant that keeps its kitchen inspection-ready every day does not panic when the inspector walks in. A restaurant that cleans only on the day of the visit is always one surprise away from a fine.
People and process matter as much as tools
Name an owner for the audit pipeline. Write a short runbook for the most likely incidents: connector down, disk filling, integrity check failing, lost key access. Rehearse the runbook. Train developers on what belongs in an audit event and what must never be logged. Most audit failures in real life come from missing ownership, not missing technology.
23Watching the Watchers: Monitoring the Audit Pipeline
An audit pipeline that fails quietly is worse than none, because everyone believes they are covered. Monitoring turns silent failures into loud ones.
The health signals of Kafka itself
Under-replicated partitions
Copies that have fallen behind. Any number above zero for long means your safety margin is shrinking.
Offline partitions
Partitions with no leader. Writes to them fail, so audit events pile up upstream.
In-sync replica shrinks
Frequent shrinking and expanding hints at network or disk trouble.
Consumer lag
How far behind a reader is. A stuck archive connector shows up as growing lag long before anyone notices missing files.
Send errors and retries
A rising error rate at the producer means events may be waiting or dropping.
Disk headroom
A full disk can stop a broker. Watch growth against your retention plan.
The completeness question: did every event arrive?
Health signals tell you the machinery is running. They do not tell you that nothing was lost. For that, use count reconciliation. Each stage of the pipeline counts how many events it saw in each short time window, and the counts are compared. If the source counted 10,000 events between 10:00 and 10:05 and the archive holds 9,998, you know two events are missing and exactly when to look.
This idea has a long history in the Kafka world. The original LinkedIn paper on Kafka described a monitoring scheme in which producers periodically publish counts so that consumers can check that no data was lost. Uber later built and described a system named Chaperone to audit its Kafka pipelines end to end, counting messages in time buckets at every tier to detect loss, duplication and delay.
A warehouse manager counts the boxes loaded onto a truck and the boxes unloaded at the destination. If the numbers differ, no one needs to inspect every box to know something went wrong.
Sequence numbers and heartbeats
Two more tricks catch gaps. Give each source a running sequence number; if a consumer sees 41 then 43, event 42 is missing. And have every producing service emit a regular heartbeat audit event, such as one per minute. A silent service that should be busy, or a missing heartbeat, is an alert by itself.
Alerts that matter to compliance
- Any change to audit topic settings, retention or ACLs.
- Any use of delete-records on an audit topic.
- Sudden drops in audit event volume from any source.
- Archive lag beyond your agreed limit.
- Failures of the integrity verifier.
- Repeated denied access attempts against the audit topics.
24Real-World Examples
Here is how the ideas above show up in practice. Some examples describe publicly known systems, and others are illustrative scenarios that show how a typical team would apply the patterns.
LinkedIn: audit counts from the very beginning
Kafka was born at LinkedIn to carry activity and operational data. Its creators built in a counting-based audit from the start, so the company could tell whether the pipeline delivered everything it was given. The lesson: completeness checking is not an add-on; it is part of trusting a streaming system.
Uber: Chaperone for end-to-end pipeline auditing
Uber runs Kafka at very large scale across regions and moves data between clusters. It described Chaperone as a service that audits the flow, counting messages per time bucket at each stage, so that loss and duplication in any hop are noticed. The lesson: when data crosses clusters, count at every crossing.
Confluent: platform audit logs written to Kafka itself
Confluent’s platform and cloud offerings record security-relevant events, such as authentication and authorization results and administrative actions, as structured events in a dedicated Kafka topic. The lesson: using Kafka to carry the audit stream of Kafka is a natural design, provided that topic is guarded and archived independently.
AWS CloudTrail: the model for tamper evidence
CloudTrail records API activity in an AWS account and offers log file integrity validation using hashes and digital signatures. Many teams copy its approach for their own pipelines: deliver to protected storage, sign, and offer a way to verify. The lesson: make verification a feature, not a special project.
Illustrative scenario: a retail bank meeting SOX and PCI DSS
A bank’s payment service writes each transfer and its audit event in one database transaction, and a relay publishes the event to an audit topic with three replicas. A connector copies events every few minutes into a locked archive, while a search index keeps the last 90 days for investigators. Card numbers are never logged; tokens stand in for them. Access changes to the audit topic raise a page to the security team. When an auditor samples a transfer from eleven months ago, the team pulls it from the archive and verifies its signed checkpoint in minutes.
Illustrative scenario: a hospital system under HIPAA
Every time a staff member opens a patient chart, the system emits an audit event with the staff identity, the patient identifier and the reason for access. A stream processor flags staff who open charts of patients they do not treat. Because patient details are encrypted with per-patient keys, a rare deletion request can be honored by destroying the key without breaking the rest of the trail.
25Design Patterns and Anti-Patterns
Patterns are proven recipes; anti-patterns are recipes for trouble. Knowing both saves months of painful learning.
Patterns worth adopting
Transactional outbox
Commit the audit event with the business change, then relay it to Kafka. No lost or phantom events.
Standard envelope with schema
One event format, enforced by a schema registry and shared library.
Fan-out consumers
Independent readers for archive, search and alerting, so failure of one never blocks the others.
Immutable sink
Copy events to locked storage so the archive survives even a compromised cluster.
Signed checkpoints
Hash chains and signatures that let anyone verify integrity later.
Per-subject encryption
Personal fields encrypted with individual keys, enabling crypto-shredding.
Dead-letter topic
Events that fail validation go to a separate topic for review instead of being dropped.
Count reconciliation
Compare counts between stages to prove completeness.
Anti-patterns to avoid
What it looks like
The service updates its database and then separately sends the audit event, with no safety net between the two steps.
Why it hurts
A crash between the steps creates a change with no record, or a record with no change. Neither is detectable later.
Do this instead
Use the outbox pattern from Chapter 8 so both are saved in one transaction.
What it looks like
The audit topic uses compaction, or a short retention period with no archive behind it.
Why it hurts
History quietly vanishes. You discover it when an auditor asks for last year’s records.
Do this instead
Use delete-based retention that matches your plan, and archive to locked storage well before data expires from Kafka.
What it looks like
Everyone uses one shared admin login for Kafka, and audit topics sit on the same cluster and under the same admins as everything else, with no independent copy.
Why it hurts
The log shows only “the admin” did it. The people who could tamper with evidence are the same people the evidence might implicate.
Do this instead
Give each person and service a unique identity, and keep the archive and signing keys under separate control.
What it looks like
Full request bodies, passwords, card numbers or health notes are dumped into audit events “to be safe”.
Why it hurts
The audit log becomes the largest pile of sensitive data in the company, and a breach of it becomes a catastrophe.
Do this instead
Record identifiers, masked values and tokens, and encrypt any field that must be kept.
What it looks like
Trusting producer clocks alone, and never checking that the pipeline delivered everything.
Why it hurts
Events appear out of order, or silently go missing, and nobody notices until it matters.
Do this instead
Keep both source time and broker time, synchronize clocks, and reconcile counts between stages.
26Trade-offs: The Honest Pros and Cons
No design is free. Here is what you gain and what you pay for when you build compliance audit logging on Kafka.
Advantages
- High throughput, so audit does not slow the business down.
- Durable, replicated storage across zones.
- Many independent readers from one source of truth.
- Replay lets you rebuild indexes and investigate history.
- Rich tooling for schemas, connectors and stream processing.
- Works well with cloud object storage for the long-term archive.
Disadvantages
- Not immutable by itself; you must add locked storage and signatures.
- Built-in cluster audit logs are text files, not structured events.
- Operating Kafka well takes skill and ongoing attention.
- Long retention on brokers is expensive without tiered storage.
- Ordering is guaranteed only within a partition.
- Extra moving parts mean more places for gaps to appear.
Decisions you will have to make
| Decision | Option A | Option B | How to choose |
|---|---|---|---|
| If auditing fails | Fail closed: refuse the action | Buffer in the outbox and continue | Fail closed for money movement and safety-critical actions; buffer for lower-risk ones |
| Detail level of authorizer logs | Denied requests only | Allowed and denied | Start with denials; add allowed logging for the most sensitive topics only |
| Where to run the audit topics | Shared cluster | Dedicated audit cluster | Dedicated cluster when regulation or risk demands strong isolation |
| Payload contents | Minimal identifiers | Before and after values | Minimal by default; add values only where the rule needs them, encrypted |
| Managed or self-run | Managed Kafka service | Self-managed cluster | Managed reduces toil; self-run gives control. Both need the same design discipline |
27Best Practices and Common Mistakes
If you are starting today, do not try to build everything at once. Here is a sensible order that delivers value early and adds protection step by step.
A rollout plan you can follow
Agree what must be audited
Sit with compliance and list the regulations that apply, the actions that matter and the retention periods required. Write them down; everything else follows from this list.
Define the envelope and schema
Publish the standard event format and put it in a schema registry with safe evolution rules.
Build the shared producer library
One library, one outbox implementation, one place to fix bugs. Teams adopt it instead of inventing their own.
Harden the audit topics
Three replicas, minimum two in sync, acknowledgements from all, no unclean elections, no compaction, and clear retention.
Secure identities and access
Unique identities, least-privilege ACLs stored as reviewed configuration, and alerts on any ACL change.
Add the immutable archive
Sink to locked object storage and set retention to match the legal period.
Add integrity proof
Hash chains and signed checkpoints, with a verifier that runs on a schedule.
Ship the cluster’s own security logs
Move broker authorizer and admin events off the brokers and into the same protected stream.
Monitor completeness
Add reconciliation, heartbeats and lag alerts so silent failures become loud ones.
Drill it
Run retrieval drills, failure drills and access reviews on a calendar, and keep the evidence for your auditors.
The most common mistakes
- Treating audit logs like debug logs. They need stricter format, retention and protection.
- Forgetting failed and denied actions. Refusals often tell the most important stories.
- Relying on Kafka alone for immutability. Add locked storage and signatures.
- Sharing credentials. Accountability disappears the moment two people use one login.
- Never testing restore and retrieval. An archive you cannot read is not an archive.
- Ignoring privacy law. Long retention and personal data need an erasure plan such as crypto-shredding.
- Letting the schema drift. Undocumented changes make old records unreadable.
- Skipping the meta-audit. Changes to audit settings and keys must themselves be recorded elsewhere.
A quick self-check before your next audit
Ask your team these questions. Any answer that is “I am not sure” points to your next piece of work.
- Can we name every system that must produce audit events, and prove each one does?
- If a broker, a zone or the connector fails tonight, can we show that no events were lost?
- Who can delete or shorten an audit topic, and would we be alerted the moment they tried?
- Could we produce a verified record from three years ago within one working day?
- Are personal fields protected, and do we know how an erasure request would be handled?
- When did we last run a tamper drill, an access review and a restore drill, and where is the evidence?
Keep a living document that maps each compliance requirement to the control that satisfies it and the evidence that proves it. Auditors love it, and it saves your team days during every review.
28Frequently Asked Questions
Quick answers to the questions that come up most when teams start this journey.
29Summary and Key Takeaways
Audit logging for compliance is less about clever technology and more about earning trust that can be checked. Kafka gives you a strong foundation. The rest is careful design.
Key Takeaways
- Two jobs, one goal: audit the Kafka platform itself, and use Kafka to carry your applications’ audit events, then join both streams together.
- Standardize the event: one envelope that answers who, what, on what, when, where and outcome, enforced by a schema and a shared library.
- Never lose an event: use the outbox pattern, acknowledgements from all replicas, three copies, and no unclean leader election or compaction.
- Kafka is append-only, not immutable: add hash chains, signed checkpoints and a write-once archive so integrity can be proven.
- Protect people’s data: record identifiers instead of secrets, encrypt everywhere, and use per-person keys so erasure and retention can coexist.
- Lock down access: unique identities, least privilege, separation of duties, and audit the auditors.
- Prove completeness and practice retrieval: reconcile counts, watch for gaps and rehearse finding old records before an auditor asks.