Skip to content

Repository files navigation

TaskFlow

TaskFlow is a distributed background job processing platform built with Go, Gin, PostgreSQL, Redis, Asynq, Docker, and Resend.

It demonstrates how production systems handle long-running work asynchronously using workers and message queues.

Features

  • Asynchronous email delivery
  • CSV export jobs
  • Redis-backed task queues (Asynq)
  • Worker-based processing architecture
  • Retry handling
  • Failed task inspection API
  • Metrics API and HTML dashboard
  • Kubernetes deployment with HPA
  • Load testing tool
  • Docker Compose for local development
  • Asynqmon monitoring

Tech Stack

  • Go 1.26.x
  • Gin
  • PostgreSQL
  • Redis
  • Asynq
  • Resend
  • Docker / Docker Compose
  • Kubernetes

Architecture

flowchart TD
    Client[Client] --> API[API Replicas]
    API --> PG[(PostgreSQL)]
    API --> Redis[(Redis / Asynq Queue)]
    Redis --> Worker[Worker Replicas]
    Worker --> PG
    Worker --> Email[Email via Resend]
    Worker --> CSV[CSV Export]
Loading
Layer Role
API Accepts task requests, persists metadata, enqueues jobs
PostgreSQL Task lifecycle and status tracking
Redis / Asynq Distributed job queue
Worker Processes email and CSV export jobs
Resend External email delivery

Deployment Models

Environment Purpose
Docker Compose Local development and quick iteration
Kubernetes Orchestration, scaling, and production-oriented demo

API Endpoints

Method Path Description
GET /health Health check (used by Kubernetes probes)
POST /tasks Create email delivery task
GET /tasks/:id Get task status
GET /failed-tasks List failed tasks
GET /metrics JSON metrics
GET /dashboard HTML metrics dashboard
POST /exports Queue CSV export job

Create Email Task

curl -X POST http://localhost:8080/tasks \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

Create CSV Export

curl -X POST http://localhost:8080/exports \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

Docker Compose (Local Development)

  1. Copy environment file:
cp .env.example .env
  1. Set RESEND_API_KEY in .env.

  2. Start services:

docker compose up --build
Service URL
API http://localhost:8080
Dashboard http://localhost:8080/dashboard
Asynqmon http://localhost:8081

Kubernetes (Scaling Demo)

See k8s/README.md for full deployment instructions.

Quick start:

# Build local images
docker build -f Dockerfile.api -t taskflow-api:local .
docker build -f Dockerfile.worker -t taskflow-worker:local .

# Deploy to taskflow namespace
kubectl apply -f k8s/

# Port-forward API
kubectl port-forward service/taskflow-api 8080:8080 -n taskflow

Kubernetes resources include:

  • API Deployment (2 replicas) with liveness/readiness probes on /health
  • Worker Deployment (2 replicas, manually scalable)
  • PostgreSQL with persistent volume
  • Redis (internal ClusterIP)
  • ConfigMap + Secret for configuration
  • API HorizontalPodAutoscaler (2–5 replicas, CPU ~70%)

Metrics

GET /metrics returns JSON:

Metric Description
total_tasks All tasks
completed_tasks Successfully completed
failed_tasks Failed tasks
pending_tasks Awaiting processing
processing_tasks Currently processing
success_rate Completed / total (%)
failure_rate Failed / total (%)
average_processing_time_ms Avg time from start to complete
total_retry_attempts Sum of retry counts
queue_depth Current Asynq queue depth
throughput_per_second Completions in last minute / 60
throughput_per_minute Completions in last minute

GET /dashboard renders a human-readable HTML view of the same data.

Load Testing

go run ./tools/loadtest --url http://localhost:8080 --tasks 1000 --concurrency 20

Example output:

TaskFlow Load Test
------------------
Tasks submitted:       1000
Tasks completed:       ...
Success rate:          ...%
Throughput:            ... jobs/sec

Scaling Benchmark

Compare worker throughput at 1, 2, and 3 replicas. See docs/benchmark.md.

kubectl scale deployment taskflow-worker --replicas=2 -n taskflow
go run ./tools/loadtest --url http://localhost:8080 --tasks 500 --concurrency 20

Worker scaling is manual. CPU-based HPA is not queue-aware; production systems typically use queue-depth metrics.

Engineering Decisions

  • Separate API and worker binaries — independent scaling and deployment
  • Asynq over raw Redis — built-in retries, scheduling, and monitoring
  • PostgreSQL for task state — durable lifecycle tracking separate from queue
  • ConfigMap + Secret in Kubernetes — non-sensitive vs sensitive config separation
  • Local Docker images — no Docker Hub dependency for local clusters
  • Manual worker scaling — honest approach without fake queue-aware HPA
  • No cloud-specific resources — portable local Kubernetes demo

Project Structure

cmd/
  api/          HTTP API server
  worker/       Background job processor
internal/
  config/       Environment configuration
  handlers/     HTTP handlers
  metrics/      Metrics service
  models/       Domain models
  repository/   PostgreSQL and Redis
  services/     Business logic
  tasks/        Asynq task definitions and processors
  email/        Resend email integration
k8s/            Kubernetes manifests
tools/loadtest/ Load testing CLI
migrations/     Database schema
docs/           Benchmark and resume templates

Screenshots

Resume Metrics

Use docs/resume-metrics-template.md to record real benchmark results.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages