DEV Community

Süleyman Y
Süleyman Y

Posted on Originally published at webpdftools.org

Building a Zero-Retention Online PDF Toolkit: Architecture, Privacy & Edge Hardware Optimization

Most web users don't think twice before uploading confidential tax records, bank statements, medical scans, or contract agreements to popular online PDF converter websites.

Yet behind the scenes, many commercial platforms store uploaded documents on persistent cloud disks, parse metadata for analytics, or hold files for hours in S3 buckets before scheduled deletion.

When building WebPDFTools.org, we set a strict architectural constraint: Zero File Retention. Documents must be processed ephemerally in volatile memory or isolated scratch spaces, streamed back to the client, and purged instantly.

Here is a look under the hood at our architecture, how we optimize CPU-heavy Ghostscript and Tesseract workloads on edge hardware, and how we handle concurrency without crashing the host.

1. High-Level Architecture

The platform runs a lightweight, decoupled stack designed for minimal overhead:

[ Client Browser ]
       |
       v (HTTPS / TLS 1.3 via Cloudflare Tunnel)
[ Reverse Proxy: Nginx (Container) ]
   +-- Static Landing Pages (Pure semantic HTML + CSS)
   +-- Rate Limiting & Burst Queuing (anti-flood buffer)
   +-- API Proxy (/api/v1/*)
       |
       v (Private Internal Docker Bridge)
[ Stirling-PDF Core Engine (JVM / Linux container) ]
   +-- Ghostscript (Optimization & Downsampling)
   +-- Tesseract OCR v5 (Searchable sandwich PDF generation)
   +-- QPDF & Apache PDFBox (Splitting, Merging, AES encryption)
   +-- LibreOffice Headless (Document conversion)
Enter fullscreen mode Exit fullscreen mode

Why Pure HTML/CSS for the Frontend?

Instead of a heavy client-side Single Page Application (SPA) with megabytes of JavaScript bundles, our landing pages - such as PDF Merge and PDF Compress - are written in semantic, zero-dependency HTML5.

  • First Contentful Paint (FCP): Under 300ms.
  • Core Web Vitals: 100/100 performance score.
  • Browser Compatibility: Works across any mobile browser without hydration lag.

2. Implementing the "Zero-Retention" Guarantee

Ensuring documents are truly ephemeral requires defense-in-depth across the container and host storage:

A. Server-Side Storage Completely Disabled

In the application configuration (settings.yml):

storage:
  enabled: false
Enter fullscreen mode Exit fullscreen mode

This forces the backend engine to reject any database persistence or archive pipeline.

B. Ephemeral Mounting

Volume mounts between the host and Docker containers are restricted strictly to read-only language dictionaries (tessdata), system configuration files, and error logs. No upload directory is ever bound to the host disk.

C. Automated Memory Sweeping

Files reside in volatile RAM buffers (/tmp/stirling-pdf) only while the transformation is actively executing.

  • As soon as the binary stream completes and HTTP headers close, the temp descriptor is unlinked.
  • A background garbage collector daemon sweeps the scratch space every 30 minutes for orphaned file pointers.
  • On container boot, all temporary namespaces are automatically purged.

3. Concurrency Control: Sequential Queuing on Edge Hardware

One of the biggest challenges when self-hosting resource-intensive workloads (such as OCR or multi-page Ghostscript compression) on low-power edge machines (like ARM64 or Raspberry Pi 5 clusters) is CPU saturation.

If 5 users simultaneously trigger a 300 DPI OCR scan or a 50-page document compression:

  • Ghostscript and Tesseract will spawn threads across all available cores.
  • CPU usage hits 100%, causing thermal throttling.
  • Essential background services (like reverse proxies or home automation) begin dropping connections.

To solve this, we implemented a 3-tier traffic-shaping pipeline:

1. Engine-Level Process Semaphore

We dialed back concurrent worker limits inside the application engine:

processExecutor:
  sessionLimit:
    libreOfficeSessionLimit: 1
    tesseractSessionLimit: 1
    ghostscriptSessionLimit: 1  # Was 8: Now strictly sequential
    ocrMyPdfSessionLimit: 1
    qpdfSessionLimit: 2         # Lightweight ops can run in pairs
Enter fullscreen mode Exit fullscreen mode

When multiple requests arrive, subsequent operations do not fail with errors. Instead, they enter an internal JVM semaphore queue. Request B waits until Request A releases the worker, and completes smoothly.

2. Nginx Request Throttling & Buffer

At the reverse proxy layer, burst traffic is buffered to prevent thread starvation:

# nginx.conf
limit_req_zone $binary_remote_addr zone=pdf_proc_limit:10m rate=2r/s;

# webpdftools.org.conf
location /api/ {
    # Queue burst requests gracefully without rejection
    limit_req zone=pdf_proc_limit burst=10;

    proxy_pass http://stirling-pdf:8080/api/;
    proxy_read_timeout 300s;
}
Enter fullscreen mode Exit fullscreen mode

Notice the absence of the nodelay flag: incoming bursts within the threshold are delayed and fed into the processing pipe at a steady, manageable rate.

3. Hard Container CPU Quotas

In Docker Compose:

services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:latest
    cpus: 2.0      # Hard ceiling: uses at most 2 cores
    mem_limit: 4g  # Prevents OOM cascade
Enter fullscreen mode Exit fullscreen mode

This guarantees that even under maximum stress, at least 50% of host compute capacity remains completely untouched for the operating system and edge services.


4. Key Takeaways & Try It Out

  1. Privacy is an architectural choice: You don't need cloud buckets or databases to build a scalable utility tool. Streaming and ephemeral processing provide superior user trust.
  2. Rate-limiting is not just for security: On edge hardware, using Nginx burst queues and engine semaphores prevents thermal collapse under unexpected traffic spikes.
  3. Keep the web fast: Dropping heavy client JS frameworks for utilities yields massive improvements in user experience and Core Web Vitals.

Check out the live implementation at WebPDFTools.org and let us know your thoughts on the architecture in the comments below!

Top comments (0)