All case studies

Founder · Product & Architecture

TrackHRS

A distributed time tracking and activity intelligence platform: desktop agent, web apps and event-driven microservices, designed and shipped end to end.

Founder & Lead ArchitectVisit trackhrs.com
12

Product components

Desktop agent, web apps and backend services

8

NestJS microservices

Independently deployable domain services

100×

Fewer immediate writes

Batching on the ingest path cuts write amplification

Turning raw desktop activity into decisions people trust

TrackHRS is a full-stack time tracking and activity intelligence platform for distributed teams. It combines a native desktop agent, two web applications and a set of event-driven microservices that capture work activity, classify it, and turn it into analytics HR and operations teams can act on.

The hard part was never the dashboard. It was the path between a keystroke on someone’s laptop and a number a manager is willing to trust. That path has to stay accurate when the network drops, stay fast when traffic spikes, and never double-count an event because two replicas processed it at once.

I designed the architecture around asynchronous pipelines, cache-first reads and multi-replica-safe processing, so each of those failure modes is handled by a specific mechanism rather than by hope.

Stack

NestJSRustTauri 2PythonFastAPIApache KafkaRedisBullMQMongoDBNext.jsDockerKubernetesJenkins
The problem

What made this hard

Accurate time tracking

Time captured across tasks and projects with reliable aggregation, even when a laptop goes offline mid-session.

Activity intelligence

Automated categorisation of activity so operational insight does not depend on people filling in timesheets.

Operational visibility

Dashboards and reporting that HR, managers and operations teams can act on in near real time.

System design

High-level architecture

Four layers, each scaling on its own terms. Clients never talk to storage directly, and nothing time-sensitive shares a path with anything slow.

Client layer

What people actually use

Desktop agentTauri 2 · Rust
Admin portalNext.js
Marketing siteNext.js

API & service layer

Domain services behind REST and gRPC boundaries

User serviceNestJS
Activity serviceNestJS
Activity providerNestJS
Projects managerNestJS
Plans & billingNestJS
NotificationsNestJS
Storage producerNestJS
Classifier APIPython · FastAPI
Auto-update serverExpress

Event & queue layer

Where slow work is decoupled from fast work

Kafka clusterIngestion & domain events
Redis clusterCache · dedup · locks
BullMQ workersBackground jobs
RabbitMQ busTargeted fan-out

Data & object storage

Durable state

MongoDB replica setDomain persistence
S3-compatible storageScreenshots & artefacts
Local SQLiteDesktop offline buffer
Service map

12 product components

Each service owns one domain and can be deployed, scaled and owned independently.

tracking/

Tauri desktop agent for activity capture and local runtime

Tauri 2RustReact

activity/

Activity ingestion and classification orchestration

NestJSKafka

activity-provider/

Read and statistics APIs for dashboards and reporting

NestJSRedis

activity_classifier/

ML and rule-based classification service

PythonFastAPI

user-service/

Auth, users, organisations, leave and payroll core domain

NestJSJWTMongoDB

projects-manager/

Project and task time duration aggregation

NestJSKafka

plans/

Subscription and billing domain

NestJS

notifications/

Email and notification processing

NestJSKafka

storage-producer/

Object upload pipeline for screenshots and artefacts

NestJSS3Cloudflare R2

auto-update/

Desktop release and update distribution server

Express

trackhrs-front/

Public marketing site and lead capture

Next.js

trackhrs-portal/

Authenticated operations and admin experience

Next.js
Architecture

The activity intelligence pipeline

This is the core of the product. Every step exists to solve a specific failure mode: duplicate events, write amplification, a slow model call blocking ingest, or a stale dashboard. Read top to bottom, it is the journey from one keystroke to one number on a manager’s screen.

  1. 1

    Desktop activity event

    Captured by the Tauri agent and sent over a secure API boundary. If the network is down, it buffers locally in SQLite first.

    Tauri 2RustSQLite
  2. 2

    Kafka topic

    High-throughput ingestion, deliberately decoupled from everything downstream so a slow consumer can never slow down capture.

    Apache Kafka
  3. 3

    Activity consumer

    Processes the stream with partition-aware scaling, so adding replicas grows throughput with the consumer group.

    NestJSConsumer groups
  4. 4

    Redis dedup

    An O(1) key check makes processing multi-replica-safe, so the same event is never counted twice.

    Redis
  5. 5

    Batch service

    Collects up to 100 items or a 5-second window before writing, giving up to 100× fewer immediate database writes on the hot path.

    Batching
  6. 6

    MongoDB bulk upsert

    A document model that fits evolving activity payloads and organisation structures, paired with indexed reporting queries.

    MongoDBReplica set
  7. 7

    BullMQ classification queue

    Classification runs as a background job, keeping latency-sensitive writes off the same path as heavier work.

    BullMQRedis
  8. 8

    Classifier API

    A bearer-key FastAPI service, so the ML lifecycle and its dependencies iterate independently of the TypeScript services.

    PythonFastAPI
  9. 9

    Classification update

    Categories are persisted. Failures fall through a circuit breaker, exponential retry and a dead-letter collection that a distributed cron reprocesses.

    Circuit breakerRetryDLQ
  10. 10

    Cache invalidation

    An invalidation event means the next dashboard read is fresh, without depending on a short TTL to expire.

    Redis
Decisions

Why these tools, and not others

Event streaming

Apache Kafka

Decouples ingestion from downstream processing and supports replay-friendly analytics workloads at high throughput.

Background work

BullMQ

Classification and delayed jobs stay off the hot path, so latency-sensitive writes stay fast.

Cache & coordination

Redis Cluster

One system covers cache acceleration, deduplication, queue backing and the distributed locks that make cron multi-replica-safe.

Persistence

MongoDB replica set

Flexible documents suit evolving activity payloads and org structures, and pair naturally with batched upserts.

Desktop client

Tauri 2 + Rust

Native-level performance and low memory overhead, with the system-level access browser-only approaches cannot reach.

ML service

Python FastAPI

Keeps model iteration and Python dependencies fully isolated from the strongly typed core platform.

Outcome

What it delivered

Production-style distributed platform

Rust desktop agent, modern web apps and microservices delivered end to end.

Up to 100× fewer immediate DB writes

Batching on the ingest path substantially reduces write amplification.

High-throughput async processing

Kafka and BullMQ absorb traffic spikes and keep pipelines resilient.

Multi-replica-safe coordination

Redis dedup keys and distributed locks keep cron and background work idempotent.

Isolated ML service

A dedicated Python classifier while the core platform stays strongly typed in TypeScript.

Full product surface

Desktop app, admin portal, marketing site, update server and the backend ecosystem behind them.

Scaling & availability

  • Microservice-oriented, independently deployable services
  • Asynchronous pipelines that absorb traffic spikes
  • Cache-first reads for low-latency dashboards
  • Explicit deduplication and idempotency controls
  • Kafka consumer groups for partition-aware horizontal scaling
  • Distributed locks so cron and reprocessor jobs run exactly once
  • MongoDB replica set for write and read resilience

Security & reliability

  • JWT authentication and role-aware APIs
  • bcrypt password hashing, with OTP and reset flows on Redis TTL
  • API key authentication for classifier calls
  • Rate limiting and secure headers across Node services
  • Retry, circuit breaker and DLQ to contain blast radius
  • Structured /health checks for readiness and liveness

Building something like this?

If any of the problems above look familiar, I can help, whether that's a full architecture or a second opinion on the one you have.

Open to remote and hybrid work worldwide