Skip to main content
Chunkr is designed to scale horizontally by increasing the number of worker replicas. This guide covers scaling strategies for different workload patterns.

Understanding Chunkr’s Architecture

Chunkr uses a distributed architecture with specialized workers:

Default Replica Configuration

The default compose.yaml is optimized for medium workloads:

Scaling Strategies

Vertical Scaling

Increase resources for individual containers:

Horizontal Scaling

Increase the number of worker replicas:
Horizontal scaling is more effective for Chunkr as it allows processing multiple documents in parallel.

Scaling for Different Workloads

High Volume, Small Documents

Characteristics: Many PDF pages, mostly text Recommended configuration:

Large Documents, Complex Layouts

Characteristics: Multi-page documents with tables, images, complex formatting Recommended configuration:

Mixed Workload

Characteristics: Variety of document types and sizes Recommended configuration:

GPU Scaling Considerations

Single GPU

With one GPU (8GB+), balance workers to avoid memory contention:
Too many replicas on a single GPU can cause out-of-memory errors. Start conservative and scale up while monitoring GPU memory.

Multiple GPUs

With multiple GPUs, scale workers proportionally: 2 GPUs:
4 GPUs:

GPU Pinning

For optimal performance, pin specific workers to specific GPUs:

CPU Scaling

For CPU-only deployments, scale more conservatively:
CPU Threading Configuration:
  • OMP_NUM_THREADS: OpenMP threads per worker
  • MKL_NUM_THREADS: Intel MKL threads per worker
  • NUMEXPR_NUM_THREADS: NumExpr threads per worker
Set thread counts to: (total_cpu_cores / replicas) to avoid over-subscription.

Load Balancing

Chunkr uses nginx for load balancing ML workers:

Segmentation Load Balancer

The nginx configuration distributes requests across all segmentation-backend replicas.

OCR Load Balancer

The load balancers automatically detect all replicas using Docker’s DNS service discovery.

Monitoring and Optimization

Monitor Queue Depth

Check Redis queue length to identify bottlenecks:
Interpretation:
  • Queue growing: Workers can’t keep up, scale up
  • Queue near zero: Workers idle, may be over-provisioned
  • Queue stable: System balanced

Monitor Worker Utilization

Identify Bottlenecks

1

Monitor queue depth

If queues are growing, workers are the bottleneck.
2

Check resource usage

  • CPU near 100%: Scale horizontally or upgrade CPU
  • GPU near 100%: Add more GPUs or increase batch size
  • Memory high: Reduce replicas or batch sizes
3

Review processing times

Check logs for average processing time per document:
4

Scale the bottleneck

Increase replicas for the slowest component first.

Scaling Commands

Scale Specific Service

Update docker-compose.yaml

For persistent scaling, update the compose file:
Then apply:

Zero-Downtime Scaling

Database Scaling

PostgreSQL is a single instance by default. For production:

Connection Pooling

Add PgBouncer for connection pooling:
Update connection string:

Read Replicas

For read-heavy workloads, add PostgreSQL read replicas and route read queries accordingly.

Redis Scaling

Redis Cluster

For high availability and better performance:

Redis Sentinel

For automatic failover:

Cost Optimization

Auto-scaling Strategy

  1. Monitor queue depth every minute
  2. Scale up when queue > 100 tasks for 2 minutes
  3. Scale down when queue < 10 tasks for 5 minutes
  4. Minimum replicas: Keep baseline capacity
  5. Maximum replicas: Set budget limits

Resource Limits

Prevent runaway resource usage:

Production Scaling Checklist

1

Baseline testing

  • Test with expected document types
  • Measure processing times
  • Identify resource bottlenecks
2

Configure monitoring

  • Set up metrics collection
  • Configure alerts for queue depth
  • Monitor GPU/CPU utilization
3

Scale incrementally

  • Start with default configuration
  • Increase replicas by 25-50% at a time
  • Monitor impact before further scaling
4

Optimize bottlenecks

  • Scale the slowest component first
  • Tune batch sizes and threading
  • Consider adding GPUs if needed
5

Set resource limits

  • Prevent memory exhaustion
  • Ensure predictable performance
  • Enable graceful degradation

Next Steps