Skip to main content

Performance Tuning

These settings control worker behavior, model inference, batch sizes, timeouts, OCR, and rate limits. Start with the symptom you are seeing, then tune the smallest matching knob.

Quick Tuning Map

SymptomFirst AdjustmentWhy
High embedding memoryLower EMBEDDING_BATCH_SIZE or MAX_NODES_PER_TASKReduces texts held per FastEmbed call and per Celery task
Slow document ingestionAdd embedding workers before increasing embedding concurrencyEach embedding worker keeps model memory isolated
Slow classificationLower CLASSIFICATION_SELECT_TOP_K or enable MODERNBERT_PREFILTER_ENABLEDScores fewer chunks/categories with ONNX
ONNX CPU oversubscriptionKeep MODERNBERT_ONNX_INTRA_OP_THREADS=1 and MODERNBERT_ONNX_INTER_OP_THREADS=1 in containersPrevents worker processes from competing for the same cores
OCR-heavy uploads are slowIncrease preprocessing capacity or raise OCR_PAGE_TEXT_THRESHOLD carefullyOCR runs in preprocessing and is CPU-heavy
Slow rerankingIncrease RERANK_TIMEOUT_SEC, reduce top_k_rerank, or disable rerankingReranking is synchronous on the search path
Too many protected-route 429sIncrease RATE_LIMIT, reduce request volume, or add an external limiter/capacity planRate limiting is per resolved client id for protected routes; /search also has a search-specific counter
Too many auth-failure 429sIncrease AUTH_FAILURE_RATE_LIMIT only after ruling out credential probingFailed auth attempts are rate limited per source address before client resolution

Embedding and Search Knobs

SettingDefaultWhy It Matters
MAX_NODES_PER_TASK50Number of chunks grouped into one embedding Celery task
EMBEDDING_BATCH_SIZE32Number of texts processed at once by FastEmbed
RETRIEVAL_TOP_K10Default number of search results
RERANK_TOP_N5Default number of reranked results returned
RERANK_TIMEOUT_SEC2.0Maximum reranking wait before falling back to hybrid scores

Classification and NER Knobs

SettingDefaultWhy It Matters
CLASSIFICATION_ENABLEDtrueDisables ModernBERT classification when set to false
SPACY_NER_ENABLEDtrueDisables entity extraction when set to false
CLASSIFICATION_SELECT_TOP_K3Number of representative chunks selected via centroid + MMR
MODERNBERT_PREFILTER_ENABLEDfalseEnables lexical prefiltering before ONNX scoring
MODERNBERT_PREFILTER_TOP_K3Number of candidate categories kept by the prefilter
MODERNBERT_ONNX_NLI_MAX_TOKENS2048Maximum NLI sequence length before truncation
MODERNBERT_ONNX_INTRA_OP_THREADS1ONNX Runtime threads within a single operator
MODERNBERT_ONNX_INTER_OP_THREADS1ONNX Runtime threads across operators
Container defaults

For Docker Compose deployments, keep ONNX thread counts at 1 unless you have measured spare CPU headroom. Increasing them can make a single classification faster while reducing total worker throughput.

OCR and Upload Knobs

SettingDefaultWhy It Matters
MAX_FILE_SIZE_MB200Upload size limit enforced before processing starts
RAPIDOCR_OCR_ENABLEDtrueEnables OCR for images and low-text PDF pages
OCR_PAGE_TEXT_THRESHOLD80PDF pages below this native text count use OCR fallback
ALLOWED_EXTENSIONSSee .env.exampleControls accepted file extensions
ALLOWED_MIME_TYPESSee .env.exampleValidates uploaded file MIME types

Office File Settings

SettingDefaultWhy It Matters
OFFICE_LEGACY_CONVERSION_ENABLEDfalseEnables LibreOffice conversion for .ppt/.xls (legacy binary formats)
OFFICE_LEGACY_CONVERSION_TIMEOUT_SEC120Timeout per legacy Office conversion; large files may need more time
LIBREOFFICE_BINARYsofficeLibreOffice executable path
OFFICE_MAX_UNCOMPRESSED_BYTES1000000000Max decompressed size for OOXML files (zip-bomb guard)
OFFICE_MAX_COMPRESSION_RATIO200Max uncompressed:compressed ratio for OOXML files

Celery Worker Knobs

SettingDefaultWhy It Matters
CELERY_WORKER_MAX_MEMORY_PER_CHILD1572864 KBBase memory recycle threshold for worker children
CELERY_WORKER_MAX_TASKS_PER_CHILD100Global task recycle threshold
CELERY_WORKER_MAX_TASKS_PER_CHILD_EMBEDDING250Embedding worker recycle threshold
CELERY_WORKER_MAX_TASKS_PER_CHILD_PREPROCESSING500Preprocessing worker recycle threshold
CELERY_TASK_MAX_RETRIES3Maximum retry attempts for recoverable task failures
CELERY_RETRY_BACKOFF_BASE60 secondsBase delay for exponential retry backoff
CELERY_RESULT_EXPIRES86400 secondsTime Celery results remain in Redis DB /2
CELERY_EMBED_SOFT_TIME_LIMIT_SEC900Soft timeout for embedding tasks
CELERY_EMBED_TIME_LIMIT_SEC1200Hard timeout for embedding tasks

Rate-Limit Knob

SettingDefaultWhy It Matters
RATE_LIMIT30Requests per minute per resolved client id for protected endpoints
AUTH_FAILURE_RATE_LIMIT10Failed authentication attempts per minute per source address

Set RATE_LIMIT=0 to disable the built-in limiter. Production traffic across multiple API workers shares Redis-backed rate-limit counters through REDIS_URL; use a reverse proxy or edge limiter only for additional network-level protection.

Status Endpoint Details

GET /status/{job_id} can return:

  • pending
  • processing
  • completed
  • failed
  • partial_failed
  • retrying

partial_failed means some embedding tasks failed while others succeeded.

When to Leave Defaults Alone

Keep the defaults when you are still validating correctness or running a small deployment. Most tuning should happen only after just status, logs, or benchmark results show a specific bottleneck.