pip install pillow reportlab And Nothing Else: What a 2 GB Server Taught Me About Dependency Bloat
Description and use
An OOM crash on a 2 GB RAM, 1 vCPU server was caused by 47 transitive dependencies. By removing unnecessary packages and keeping only Pillow and reportlab, plus single‑process execution, gc.collect(), and subprocess isolation, the pipeline now reliably processes 1,700 assets without memory exhaustion.
Problem
An image rendering pipeline on a 1 vCPU, 2 GB RAM server crashed with OOM due to excessive transitive dependencies in a “simple” automation stack.
Outcome
The refactored pipeline runs on a 1 vCPU, 2 GB RAM server without OOM errors, processes 1,700 assets, and produces 856 MB of output using only four scripts and two third‑party packages.
Workflow
- Measure peak RSS with resource.getrusage(RUSAGE_SELF).ru_maxrss after each batch
- Delete unnecessary dependencies and rewrite scripts to use only stdlib
- Limit image jobs to one process at a time, call gc.collect() between items
- Run heavy render steps in separate subprocesses to return memory to OS
- Inspect previews at 60 dpi instead of 300 dpi
- Create one script per concern: make_metadata.py, upload_tracker.py, pack_product.py, md2pdf.py
- Use a ledger file to track upload status and prevent double‑posting
- Adopt a fixed folder layout (assets/, output/, packs/, research/, scripts/)
- Package the four scripts and layout into a Pipeline Starter Kit
Evidence
I hit the wall at 2:40 on a Tuesday afternoon. My server, a 1 vCPU box with 2 GB of RAM and no GPU, had just killed an image render with an OOM error.
The task queue alone sat at a few hundred megabytes before it did any work.
The fix was not optimization. It was deletion. My metadata generation and upload tracking now run on the standard library alone.
The scripts that do need help, image covers and PDF rendering, import exactly two packages: Pillow and reportlab.
On a 1-core box, I also stopped fanning out image jobs in parallel. One process at a time, gc.collect() between items, and heavy render steps in their own subprocess so memory returns to the OS.
- Record date: 2026-10-27T18:11:13.670Z