feat(pii): env-driven uvicorn worker count (PII_WORKERS)#5457
Conversation
Launch the Presidio service with --workers from the PII_WORKERS env var so one image scales per task size (set PII_WORKERS = the task's vCPU count) without a rebuild. `sh -c exec` expands the var while keeping uvicorn as PID 1 for clean SIGTERM. Defaults to 1, so local/self-hosted is unchanged. Each worker loads the spaCy models independently (~3.3GB measured), so task memory must be sized to PII_WORKERS x ~3.3GB + overhead (set in infra alongside PII_WORKERS).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview Health check Comments document sizing guidance: ~3 GB RAM per worker and quoting the env expansion so bad values fail uvicorn parsing instead of shell misinterpretation. Reviewed by Cursor Bugbot for commit 044eb3d. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
@greptile review |
Greptile SummaryThis PR adds env-driven uvicorn worker scaling to the Presidio PII service by replacing the static
Confidence Score: 4/5Safe to merge for the core use case; the only open questions are input validation on the worker count and whether the 180s health-check window holds under a cold multi-worker start. The change is minimal and well-reasoned: sh -c exec correctly promotes uvicorn to PID 1, the default of 1 preserves existing local/single-worker behavior, and Debian dash fully supports ${VAR:-default}. The two gaps — no guard against a malformed PII_WORKERS value causing a cryptic startup failure, and the hardcoded 180s start period that was never validated against a multi-worker cold boot — are non-blocking but worth addressing before scaling to higher worker counts in production. docker/pii.Dockerfile — the CMD line and the HEALTHCHECK start-period both warrant a second look when PII_WORKERS will be set to values greater than 2. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Container starts] --> B{PII_WORKERS set?}
B -- No --> C[Default: --workers 1]
B -- Yes --> D[Use PII_WORKERS value]
C --> E[sh -c exec uvicorn ...]
D --> E
E --> F[exec replaces sh - uvicorn is PID 1]
F --> G[uvicorn master binds :5001]
G --> H[Spawns N worker processes]
H --> I[Each worker loads spaCy models independently ~3.3 GB/worker]
I --> J[Workers ready - /health responds 200]
J --> K[HEALTHCHECK passes within 180s start-period]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Container starts] --> B{PII_WORKERS set?}
B -- No --> C[Default: --workers 1]
B -- Yes --> D[Use PII_WORKERS value]
C --> E[sh -c exec uvicorn ...]
D --> E
E --> F[exec replaces sh - uvicorn is PID 1]
F --> G[uvicorn master binds :5001]
G --> H[Spawns N worker processes]
H --> I[Each worker loads spaCy models independently ~3.3 GB/worker]
I --> J[Workers ready - /health responds 200]
J --> K[HEALTHCHECK passes within 180s start-period]
Reviews (2): Last reviewed commit: "feat(pii): env-driven uvicorn worker cou..." | Re-trigger Greptile |
…riod for multi-worker
- Quote ${PII_WORKERS} so a malformed value fails uvicorn arg-parsing instead of
being shell-interpreted (verified: '1; echo X' rejected as non-integer, X not run)
- Bump HEALTHCHECK start-period 180s -> 300s: N workers load the spaCy models in
parallel, stretching cold start beyond the single-worker case
|
@greptile review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 044eb3d. Configure here.
| # `sh -c exec` expands the env var while keeping uvicorn as PID 1 for clean SIGTERM. | ||
| # Quote the expansion so a malformed PII_WORKERS fails uvicorn arg-parsing rather | ||
| # than being interpreted by the shell. | ||
| CMD ["sh", "-c", "exec uvicorn server:app --host 0.0.0.0 --port 5001 --workers \"${PII_WORKERS:-1}\""] |
There was a problem hiding this comment.
Supervisor duplicates spaCy model RAM
High Severity
With PII_WORKERS greater than one, the new --workers flag turns on uvicorn’s multiprocess supervisor. The image’s pinned uvicorn 0.49.0 eagerly imports server:app in that supervisor before workers start, so the five spaCy models load once in the parent and again in each worker. Task memory sized as PII_WORKERS × ~3 GB can OOM or thrash during rollout.
Reviewed by Cursor Bugbot for commit 044eb3d. Configure here.
There was a problem hiding this comment.
this is fine. I can tune this manually.


Summary
--workersfrom aPII_WORKERSenv var, so one image scales per task size (setPII_WORKERS= the task's vCPU count) with no rebuild.sh -c execexpands the var while keeping uvicorn as PID 1 for clean SIGTERM. Defaults to1, so local/self-hosted behavior is unchanged.Why
Each Presidio task currently runs a single uvicorn worker → uses 1 of its 2 vCPUs, so the fleet processes very few NER requests in parallel while the app fans out many → queueing → ALB 504s under load. Making worker count env-driven lets us run one worker per vCPU without per-env images.
Coupling (infra PR)
Each worker loads the spaCy models independently (~3.3 GB measured), so task memory must be sized to
PII_WORKERS × ~3.3 GB + overhead. The infra PR setsPII_WORKERS(derived from vCPU) and bumps task cpu/memory accordingly, plus raises the ALB idle timeout and caps the app fan-out.Testing
PII_WORKERS=2→ uvicorn multi-worker mode (Started parent process);PII_WORKERS=1→ single worker,/health+/redact_batchOK. Measured 3.28 GB RSS per worker.Type of Change
Checklist
🤖 Generated with Claude Code