kafka-rs

Architecture Overview

System Design Philosophy

Kafka-RS follows Domain-Driven Design (DDD) principles to create a clear separation between business logic and technical implementation. This makes the codebase educational and easier to understand.

High-Level Architecture

┌─────────────────────────────────────────────────────────┐
│                   Client Layer                          │
│  (KafkaJS, kafka-node, or any Kafka client)           │
└─────────────────────────┬───────────────────────────────┘
                          │ TCP/Kafka Protocol
┌─────────────────────────▼───────────────────────────────┐
│                Infrastructure Layer                     │
│  ┌─────────────────┐  ┌─────────────────┐             │
│  │   TCP Server    │  │   Protocol      │             │
│  │   (Tokio)       │  │   Handler       │             │
│  └─────────────────┘  └─────────────────┘             │
└─────────────────────────┬───────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────┐
│                Application Layer                        │
│  ┌─────────────────┐  ┌─────────────────┐             │
│  │  Producer       │  │  Consumer       │             │
│  │  Service        │  │  Service        │             │
│  └─────────────────┘  └─────────────────┘             │
└─────────────────────────┬───────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────┐
│                  Domain Layer                           │
│  ┌──────────┐ ┌──────────┐ ┌─────────────┐            │
│  │  Topic   │ │ Message  │ │ Partition   │            │
│  │ Entity   │ │ Entity   │ │ Entity      │            │
│  └──────────┘ └──────────┘ └─────────────┘            │
│  ┌─────────────────┐  ┌─────────────────┐             │
│  │   Domain        │  │  Repository     │             │
│  │   Services      │  │  Interfaces     │             │
│  └─────────────────┘  └─────────────────┘             │
└─────────────────────────┬───────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────┐
│              Infrastructure Layer (Storage)             │
│  ┌─────────────────┐  ┌─────────────────┐             │
│  │  In-Memory      │  │  Offset         │             │
│  │  Topic Store    │  │  Manager        │             │
│  └─────────────────┘  └─────────────────┘             │
└─────────────────────────────────────────────────────────┘

Layer Responsibilities

1. Domain Layer (src/domain/)

Purpose: Contains the core business logic and rules

Components:

Key Principles:

2. Application Layer (src/application/)

Purpose: Orchestrates use cases and coordinates between layers

Components:

Responsibilities:

3. Infrastructure Layer (src/infrastructure/)

Purpose: Handles external concerns and technical implementation

Components:

External Dependencies:

Domain Model Core Concepts

Topic

A named channel for organizing messages. In Kafka-RS, topics are:

Message

The fundamental unit of data with:

Partition

A subset of a topic that:

Consumer

An entity that:

Producer

An entity that:

Message Flow

Producer Flow

  1. Client sends produce request
  2. Protocol layer parses request
  3. Application service validates input
  4. Domain service routes to partition
  5. Message stored with offset
  6. Acknowledgment sent to client

Consumer Flow

  1. Client sends fetch request
  2. Protocol layer parses request
  3. Application service retrieves messages
  4. Domain service applies offset logic
  5. Messages serialized and sent
  6. Consumer updates offset

Concurrency Model

Thread Safety

Async Design

Storage Strategy

In-Memory Storage

Trade-offs

Protocol Compatibility

Kafka Wire Protocol

We implement a subset of Kafka’s binary protocol:

Simplified Implementation

Observability

Educational Logging

Every operation logs detailed information:

log::info!("Received produce request for topic: {}", topic_name);
log::debug!("Storing message with offset: {}", offset);
log::info!("Consumer {} fetched {} messages", consumer_id, count);

Metrics (Future)

Design Patterns Used

Repository Pattern

Abstract storage behind interfaces:

trait TopicRepository {
    async fn save_topic(&self, topic: Topic) -> Result<()>;
    async fn find_by_name(&self, name: &TopicName) -> Option<Topic>;
}

Service Layer Pattern

Encapsulate business operations:

struct MessageService {
    topic_repo: Arc<dyn TopicRepository>,
}

Builder Pattern

Complex object construction:

Message::builder()
    .key("user-123")
    .value("user data")
    .timestamp(now())
    .build()

Testing Strategy

Unit Tests

Integration Tests

Educational Focus

Tests serve as documentation and examples of expected behavior.

Future Extensions

This architecture supports adding:

The DDD structure makes these extensions clear about where new functionality belongs.