All projects
Interview challenge

WIT — Distributed Calculator

2025·Solo build
KafkaDockerMicroservicesREST API

WIT — Distributed Calculator

Microservices-based calculator built as a take-home assessment, focused on async messaging and service orchestration.

The brief

Build a calculator. The twist: distribute the work across multiple services that communicate asynchronously. The point isn't the math — it's whether you can think in distributed-systems primitives.

Architecture

A small constellation of services that pass calculation requests through a message bus, process them independently, and return results without tight coupling.

Client
  ↓
API Gateway → Kafka topic: requests
                    ↓
            Worker services (consume, compute, publish)
                    ↓
            Kafka topic: results
                    ↓
            API Gateway
                    ↓
                  Client

Key decisions

Kafka, not RabbitMQ or Redis Streams. The brief wanted async messaging at scale — Kafka is the canonical choice when you want partition-based parallelism and durable replay. RabbitMQ would have been simpler but less honest to the problem.

Stateless workers. Workers don't share memory and don't depend on each other. Adding capacity is docker-compose up --scale worker=N. This is the actual point of the architecture — not the calculation.

Idempotent processing. Each request carries a UUID. Workers check it before computing, so retries from the broker don't double-process. Cheap to add upfront, expensive to add later.

No persistence layer. The brief didn't require one. I deliberately didn't add it — scope creep on a take-home is its own red flag.

Stack rationale

| Layer | Tech | Why | |---|---|---| | Messaging | Kafka | Partitioning, durability, replay | | Services | Python microservices | Fast iteration, easy to read | | Orchestration | Docker Compose | Reproducible local cluster | | Entry point | REST gateway | Familiar surface for clients |

Reflection

What I'd add for production: a dead-letter queue for poison messages, observability via OpenTelemetry, schema registry for the Kafka payloads, and a circuit breaker on the gateway. The skeleton is correct — these are operational hardening, not architectural changes.