Skip to content

Architecture Lab

Kafka Fundamentals

Streams, topics, and durable event backbones.

Topics, partitions, consumer groups, offsets, and durable event backbones

Kafka is frequently introduced as a message queue. That description is useful, but incomplete.

A better mental model is:

Kafka is a distributed, replicated, append-only log in which producers write records and consumers independently track their position.

Unlike a traditional queue, reading a record does not immediately remove it. Kafka retains records according to the topic’s retention policy, allowing multiple consumer groups to process the same history independently or replay earlier records.

Kafka’s core mental model

A Kafka-based system normally contains:

  • Producers
  • Topics
  • Partitions
  • Brokers
  • Consumer groups
  • Offsets

The basic flow is:

Producer
   ↓
Topic partition
   ↓
Consumer group

However, several independent consumer groups can read the same topic.

For example, the same Order Created record may be processed by:

  • Fulfilment
  • Fraud detection
  • Analytics
  • Customer notifications
  • Search indexing

Each consumer group maintains its own progress.

Figure 1: Producers append records to a durable topic, while independent consumer groups maintain separate offsets.

Kafka does not delete a record merely because one consumer has processed it. The record remains available until retention or compaction removes it. This is what makes replay, backfills, and independent consumption possible.

Producers

A producer creates records and sends them to Kafka.

A record normally contains:

Topic
Key
Value
Timestamp
Headers

After Kafka accepts it, the record is assigned:

Partition
Offset

Example event:

{
  "eventId": "evt-8821",
  "eventType": "OrderCreated",
  "orderId": "order-9014",
  "customerId": "customer-221",
  "amount": 4250,
  "currency": "INR",
  "occurredAt": "2026-07-31T10:30:00Z"
}

The producer should publish stable business facts rather than expose its internal database representation.

Prefer:

Order Created
Payment Authorized
Inventory Reserved

Avoid:

Order Table Row Updated
Payment Status Column Changed

The first set expresses business meaning. The second leaks implementation details.

Topics

A topic is a named stream of records.

Examples:

orders.events
payments.events
inventory.changes
customer-profile.events

A topic should normally represent a stable domain stream rather than one specific consumer.

Good:

payments.events

Risky:

notification-service-input

The second name couples the producer to today’s consumer. If the notification service changes, the topic design may no longer make sense.

Consumer-specific work topics can still be appropriate when the semantics are explicitly task-oriented, but domain events should usually be named after the facts they represent.

Partitions

A Kafka topic is divided into one or more partitions.

Each partition is an ordered append-only log.

Partition 0

Offset 0
Offset 1
Offset 2
Offset 3

A topic with three partitions may look like:

Partition 0: 0 → 1 → 2 → 3
Partition 1: 0 → 1 → 2
Partition 2: 0 → 1 → 2 → 3 → 4

Kafka guarantees ordering within a partition. It does not provide one global ordering across every partition in a topic.

Partitions provide:

  • Parallel producer throughput
  • Parallel consumer processing
  • Horizontal storage distribution
  • A defined ordering boundary
  • Failure isolation across partition replicas

Increasing the number of partitions can increase possible parallelism, but it also introduces more metadata, replication traffic, open files, assignment work, and rebalance activity.

Partition count should therefore be treated as an architectural decision rather than an arbitrary large number.

Keys and ordering

A producer can attach a key to each record.

The key is commonly used to determine which partition receives the record.

For example:

Key: order-9014

All records for that order can be routed to the same partition:

Order Created
Inventory Reserved
Payment Authorized
Order Shipped

This preserves order for that business entity.

Figure 2: Records with the same key are routed to the same partition, preserving order for that key.

A useful key may be:

  • Order ID
  • Account ID
  • Customer ID
  • Payment ID
  • Device ID
  • Merchant ID

The correct key depends on the ordering requirement.

Example: order events

Using orderId as the key ensures that events for one order remain ordered.

order-101 → Partition 1
order-202 → Partition 0
order-101 → Partition 1

Example: account ledger events

Using accountId can ensure that ledger changes for one account are processed sequentially.

The hot-partition problem

A poor key may send too much traffic to one partition.

Examples:

  • One global tenant ID
  • One very large merchant
  • One celebrity account
  • A constant default key
  • Missing keys routed to the same partition

A hot partition limits throughput even when the rest of the topic has unused capacity.

Possible mitigations include:

  • Choose a more granular key
  • Isolate exceptionally large tenants
  • Split workloads when ordering permits
  • Aggregate before producing
  • Accept serialization when correctness requires it

Do not randomly distribute records when the application requires per-key ordering.

Brokers and clusters

A Kafka cluster contains one or more brokers.

Each broker stores partitions and serves producer and consumer requests.

For a replicated partition, one broker acts as the leader and other brokers hold follower replicas.

Partition 0

Broker 1: Leader
Broker 2: Follower
Broker 3: Follower

Producers and consumers interact with the partition leader. Followers replicate the leader’s log.

If the leader becomes unavailable, an eligible replica can take over according to the cluster’s replication and election rules.

Replication factor alone does not define durability. Durability also depends on:

  • Producer acknowledgement mode
  • In-sync replicas
  • Minimum in-sync replica configuration
  • Replica health
  • Leader election policy
  • Disk reliability
  • Operational procedures

Consumer groups

Consumers sharing the same group identifier cooperate as one logical consumer.

Kafka distributes topic partitions among the consumers in that group.

Suppose a topic has three partitions:

Partition 0
Partition 1
Partition 2

A group containing three consumers can assign:

Consumer A → Partition 0
Consumer B → Partition 1
Consumer C → Partition 2

Within one conventional consumer group, each partition is assigned to one consumer at a time. This assignment allows parallel processing without two consumers in the same group simultaneously processing the same partition.

Figure 3: A consumer group distributes partition ownership while committed offsets preserve progress.

More consumers than partitions

If a topic has three partitions and the consumer group has four consumers:

Consumer A → Partition 0
Consumer B → Partition 1
Consumer C → Partition 2
Consumer D → Idle

The fourth consumer cannot increase parallelism until more partitions exist.

Partition count therefore sets the upper bound on parallelism for a conventional consumer group.

Independent consumer groups

Different groups consume the same topic independently.

Example:

Fulfilment Group
Fraud Group
Analytics Group
Notification Group

Each group has:

  • Its own partition assignments
  • Its own offsets
  • Its own processing speed
  • Its own retry behaviour
  • Its own replay position

One slow analytics consumer does not directly change the fulfilment group’s offset.

Offsets

An offset identifies a record’s position within one partition.

Partition 2
Offset 17421

Offsets are local to a partition.

This means:

Partition 0, Offset 100

and:

Partition 1, Offset 100

refer to different records.

A consumer tracks its current position and can commit offsets so that processing can resume after a restart. Kafka stores committed offsets for consumer groups and uses them to restore progress.

Current position versus committed position

The current position is where the running consumer has read.

The committed position is the durable recovery checkpoint.

These may differ while records are being processed.

When should offsets be committed?

Offset timing affects delivery semantics.

Commit before processing

Read record
Commit offset
Process record

If the process crashes after committing but before completing the work, that work may be lost.

This approximates at-most-once processing.

Process before committing

Read record
Process record
Commit offset

If the process completes the work but crashes before committing, the record may be processed again after restart.

This provides at-least-once processing.

Most business applications choose at-least-once processing and make downstream effects idempotent.

Rebalancing

A rebalance occurs when Kafka changes partition ownership within a consumer group.

Common triggers include:

  • A consumer joins
  • A consumer leaves
  • A consumer crashes
  • Topic partitions change
  • Group membership changes

During a rebalance:

  • Existing assignments may be revoked
  • Partitions are reassigned
  • Processing may pause
  • In-flight work must be completed or safely abandoned
  • New consumers resume from committed offsets

Current Kafka versions also support the newer consumer rebalance protocol, introduced as generally available from Kafka 4.0, with a more incremental design intended to reduce rebalance disruption.

Regardless of protocol, applications should monitor:

  • Rebalance frequency
  • Rebalance duration
  • Consumer restarts
  • Partition movement
  • Processing pauses

Frequent rebalances may indicate unstable consumers, overly long processing, deployment churn, or unsuitable timeout settings.

Replication and durability

Kafka replicates partitions across brokers to protect against broker failure.

A partition may have:

Replication factor: 3

Broker 1: Leader
Broker 2: Follower
Broker 3: Follower

The producer’s acknowledgement configuration determines how much confirmation it waits for before considering a write successful.

Figure 4: Producer acknowledgement modes provide different latency and durability trade-offs.

acks=0

The producer does not wait for a broker acknowledgement.

Benefits:

  • Lowest acknowledgement latency

Risks:

  • The producer may not know whether Kafka accepted the record
  • Records may be lost without an application-visible error

Use only when losing data is acceptable.

acks=1

The partition leader acknowledges after accepting the write.

Benefits:

  • Lower latency than waiting for replicas

Risk:

  • The leader may fail before followers replicate the acknowledged record

acks=all

The leader waits for the required in-sync replicas before acknowledging.

Benefits:

  • Stronger durability

Costs:

  • Higher acknowledgement latency
  • Reduced write availability when insufficient replicas are in sync

A common production durability configuration uses replication together with acks=all and an appropriate min.insync.replicas value. Apache Kafka’s broker documentation gives the example of replication factor three, minimum in-sync replicas two, and producer acknowledgements set to all.

In-sync replicas

An in-sync replica is sufficiently caught up with the partition leader according to Kafka’s replica-management rules.

The in-sync replica set matters because acks=all does not necessarily mean every configured replica. It means the write must satisfy the required in-sync replica policy.

If too few replicas remain available:

  • Writes may be rejected
  • The system protects durability by reducing availability
  • Operators must restore broker or replica health

This is a deliberate consistency and availability trade-off.

Idempotent producers

A producer may retry a send after a network failure without knowing whether the first attempt succeeded.

Without protection, that retry could append a duplicate record.

Kafka supports idempotent producer behaviour that allows the broker to detect retry duplicates for the relevant producer and partition sequence.

Idempotent production protects records written to Kafka.

It does not automatically make an external business operation idempotent.

For example:

Consume Payment Authorized
      ↓
Call fulfilment database
      ↓
Commit Kafka offset

The database write still needs its own idempotency or atomic coordination.

Delivery semantics

Kafka discussions commonly use three delivery categories.

At-most-once

Records may be lost but are not deliberately processed again.

Typical approach:

Commit offset
Process record

At-least-once

Records should not be lost, but may be processed more than once.

Typical approach:

Process record
Commit offset

Consumers must make business effects idempotent.

Exactly-once

Kafka supports transactional processing that can atomically combine writes to Kafka topics with consumer-offset updates. Kafka Streams uses these capabilities for exactly-once processing within its Kafka-integrated processing boundary.

The boundary matters.

Kafka transactions can coordinate:

Read from Kafka
Process
Write to Kafka
Commit consumed offsets

They do not automatically make arbitrary external operations transactional.

Examples requiring additional design:

  • Writing to a relational database
  • Calling a payment provider
  • Sending an email
  • Updating an external search service
  • Invoking a third-party API

For those effects, use patterns such as:

  • Idempotent operations
  • Transactional inbox
  • Transactional outbox
  • Database constraints
  • Operation identifiers
  • Reconciliation

Retention

Kafka retains records independently of whether consumers have read them.

Retention may be based on:

  • Time
  • Log size
  • Compaction policy
  • A combination of policies

Example:

Retain order events for seven days

A consumer can replay any offset that is still retained.

This supports:

  • Recovery
  • Backfills
  • New consumer groups
  • Rebuilding projections
  • Auditing
  • Debugging
  • Reprocessing after defects
Figure 5: Standard retention preserves history for a window, while compaction retains the latest value for each key.

Retention is not archiving

Kafka retention should not automatically be treated as permanent archival storage.

Long-term regulatory or analytical retention may require:

  • Object storage
  • Data lake storage
  • Warehouse ingestion
  • Compliance archives
  • Backup and restore procedures

Log compaction

Log compaction retains at least the latest value associated with each key, subject to Kafka’s compaction process.

Example records:

customer-7 → version 1
customer-7 → version 2
customer-9 → version 1
customer-7 → version 3

After older values are compacted, the topic retains the latest known value for each key:

customer-7 → version 3
customer-9 → version 1

Compacted topics are useful for:

  • Current customer profiles
  • Configuration
  • Reference data
  • Entity state
  • Cache reconstruction
  • Table-style streams

A tombstone record, typically a key with a null value, can represent deletion.

Compaction is asynchronous. Consumers may observe multiple historical versions before the broker removes older segments.

Replay

A consumer can reset its position and reprocess retained records.

Replay is useful when:

  • A projection contains a bug
  • A downstream database must be rebuilt
  • A new feature needs historical data
  • A security rule must be reapplied
  • An incident requires reconstruction
  • A consumer missed processing during an outage

Replay must be designed safely.

Questions to ask:

  • Are consumer operations idempotent?
  • Can old events still be interpreted?
  • Are event schemas backward compatible?
  • Could replay trigger customer notifications again?
  • Could replay recreate financial effects?
  • Is the destination empty or being updated in place?
  • How will progress be monitored?
  • Can replay overwhelm downstream systems?

A replay button without guardrails is an operational risk.

Schema design and evolution

Kafka records often outlive the producer version that created them.

A good event contract should include:

Event ID
Event type
Schema version
Business key
Occurred time
Producer
Correlation ID
Causation ID
Payload

Prefer additive evolution:

Add an optional field

Avoid abrupt breaking changes:

Rename or reinterpret an existing field

Useful practices include:

  • Schema registry
  • Compatibility checks
  • Consumer-driven tests
  • Versioned events when necessary
  • Clear field semantics
  • Deprecation windows
  • Data classification

Do not rely only on JSON being syntactically valid. Semantic compatibility matters.

Consumer lag

Consumer lag is the difference between the latest available offset and a consumer group’s progress.

Conceptually:

Log end offset: 10,000
Committed offset: 9,200
Lag: 800 records

Kafka tooling exposes current offset, log-end offset, and lag for consumer groups.

Lag is important, but record count alone is not enough.

Eight hundred records may represent:

  • A few milliseconds of traffic
  • Several hours of expensive processing
  • One very large batch
  • One overloaded partition

Also track:

  • Event age
  • Oldest unprocessed record
  • Processing throughput
  • Partition-level lag
  • Retry volume
  • Rebalance duration
  • Downstream latency

Delivery semantics and operational health

    
Figure 6: Delivery guarantees must be understood together with consumer lag, event age, retries, and partition health.

The most useful operational question is not always:

How many records behind is the consumer?

It may be:

How old is the oldest business event that has not completed processing?

For a payment system, 500 records of lag may be less important than one payment event waiting for 20 minutes.

Backpressure

Kafka decouples producers and consumers in time.

If producers temporarily publish faster than consumers can process, Kafka retains the backlog.

This absorbs bursts, but capacity is not unlimited.

If consumers remain slower than producers:

  • Lag grows
  • Disk usage increases
  • Retention may expire before processing catches up
  • Replays become longer
  • Downstream systems may receive a catch-up surge
  • Old business actions may no longer be valid

Possible controls include:

  • Consumer autoscaling
  • Bounded concurrency
  • Batch-size tuning
  • Pause and resume
  • Rate limiting
  • Load shedding
  • Downstream bulkheads
  • Priority topics
  • Capacity planning

Failure handling

A consumer should classify failures rather than retry every error forever.

Transient technical failure

Examples:

  • Temporary database outage
  • Network timeout
  • Rate limit
  • Dependency unavailable

Response:

  • Retry with bounded exponential backoff
  • Add jitter
  • Preserve ordering requirements
  • Stop after a defined budget

Permanent technical failure

Examples:

  • Invalid schema
  • Missing required configuration
  • Unsupported event version
  • Corrupted payload

Response:

  • Quarantine
  • Alert the owning team
  • Repair or transform the record
  • Replay deliberately

Business rejection

Examples:

  • Order already cancelled
  • Payment cannot be refunded
  • Account is blocked
  • Inventory operation is no longer valid

Response:

  • Record the domain outcome
  • Do not retry forever
  • Publish a rejection event where appropriate

Poison records

One record may repeatedly block progress for its partition.

Possible approaches include:

  • Parking-lot topic
  • Dead-letter topic
  • Controlled skip policy
  • Manual correction
  • Side-channel retry

A dead-letter topic needs:

  • Ownership
  • Retention
  • Alerting
  • Security controls
  • Repair instructions
  • Replay tooling

Without those controls, it becomes a hidden graveyard.

Ordering versus retry

Partition ordering creates a difficult failure decision.

Suppose:

Offset 100 fails
Offset 101 is valid
Offset 102 is valid

Options include:

Block the partition

Preserves strict order but delays all later records.

Retry asynchronously

Improves throughput but may change observable order.

Move the failed record aside

Allows progress but may violate business dependencies.

Stop and escalate

Appropriate for high-value financial or ledger events.

The correct choice depends on the domain.

For account-ledger updates, strict ordering may be essential.

For analytics events, processing a later event first may be acceptable.

Observability

Monitor the Kafka platform itself:

  • Broker availability
  • Offline partitions
  • Under-replicated partitions
  • In-sync replica changes
  • Produce latency
  • Fetch latency
  • Disk usage
  • Network saturation
  • Controller health

Monitor consumer behaviour:

  • Consumer lag
  • Event age
  • Rebalance rate
  • Retry rate
  • Dead-letter volume
  • Processing latency
  • Partition skew

Monitor business completion:

  • Orders published versus fulfilled
  • Payments authorized versus recorded
  • Events produced versus projections updated
  • Inventory changes versus search-index updates

Kafka can be technically healthy while the business pipeline is broken.

When Kafka is a strong fit

Kafka is useful when the system needs:

  • Durable event streams
  • Multiple independent consumers
  • Replay and backfill
  • High-throughput event ingestion
  • Stream processing
  • Change-data capture
  • Materialized views
  • Event-driven integration
  • Audit history within a defined retention window

Examples include:

  • Order-event backbones
  • Payment-event streams
  • Customer-activity streams
  • Telemetry pipelines
  • Search-index updates
  • Data-platform ingestion
  • Fraud-feature pipelines

When a simpler queue may be better

A simpler queue may be preferable when:

  • One consumer owns each task
  • Replay is unnecessary
  • Throughput is moderate
  • Per-message acknowledgement is the primary need
  • Tasks should disappear after completion
  • Operational simplicity is more important
  • The team does not need retained event history

Kafka should not be adopted merely because it is associated with high scale.

The system should benefit from Kafka’s defining properties:

  • Durable logs
  • Partitioned ordering
  • Independent consumer positions
  • Replay
  • Replication

Key trade-offs

Benefit Cost
Durable shared event history More operational infrastructure
Independent consumer groups Schema and ownership governance
Partition-based scaling Ordering is limited to partitions
Replay and backfill Reprocessing must be safe
High-throughput ingestion Partition and broker capacity planning
Replication and durability Latency and availability trade-offs
Asynchronous decoupling Eventual consistency
Stream-processing support More complex failure handling

Design review checklist

Before approving a Kafka design, ask:

  • What is the business meaning of the topic?
  • Is this an event stream or a work queue?
  • What is the record key?
  • What ordering scope is required?
  • How many partitions are needed?
  • Can one key create a hot partition?
  • What replication and acknowledgement guarantees are required?
  • When are consumer offsets committed?
  • Are consumers idempotent?
  • What is the retention period?
  • Is log compaction appropriate?
  • Can consumers safely replay?
  • How are schemas evolved?
  • How are poison records handled?
  • What happens during rebalancing?
  • Which metric represents business freshness?

Final perspective

Kafka is not valuable simply because it transfers records quickly.

Its architectural value comes from creating a durable, replicated timeline from which independent systems can build their own state.

That capability depends on several deliberate decisions:

  • Topic ownership
  • Record keys
  • Partition count
  • Ordering scope
  • Replication
  • Producer acknowledgements
  • Offset management
  • Replay safety
  • Failure handling
  • Observability

The strongest mental model is:

Producers append facts. Kafka preserves the ordered partition logs. Consumer groups independently decide how and when to process them.

Back to Architecture Lab