AEM Forms Backend Developer Professional study materials
AEM Forms Backend Developer Professional study resources

Output service PDF generation times out under batch load

AEM Forms Backend Developer Professional · Put your knowledge to work in context.

All case studies

Output service PDF generation times out under batch load

A nightly batch generates 25,000 personalized PDFs using AEM Forms Output service on a 2-node AEM 6.5 author/publish cluster (each node 8 vCPU, 16 GB heap). Each PDF merges a 12-page XDP template with a 40-field XML record and applies a digital signature via a separate Assembler step. The batch is driven by a single OSGi service using OutputService.generatePDFOutput in a loop with a shared FormsServiceClient obtained once. Symptoms: heap climbs to 15.5 GB within 40 minutes, Full GC pauses of 8-12 s, and OutputServiceException: timeout after 60 s per record. Throughput is ~6 PDFs/min vs. the 400/min target. The signature step is synchronous and re-reads the same 3 MB keystore per record.

1. Identify the primary resource leaks and concurrency mistakes, and propose a corrected execution model.

Read the worked answer

Primary issues:

  1. Unbounded in-memory PDFs. generatePDFOutput returns a Document/byte[] held in the loop; if results are accumulated or not closed, 25k × multi-MB PDFs exhaust the heap. Stream each result to disk/object storage and null references.

  2. Shared client misuse. A single FormsServiceClient reused across threads is not guaranteed thread-safe for all operations; and a single-threaded loop cannot hit 400/min. Use a bounded thread pool sized to CPU (e.g., 6-8 workers per node) with a client per worker or a documented thread-safe pool.

  3. Keystore re-read per record. Loading a 3 MB keystore 25k times dominates time; cache the keystore/credential in a singleton and reuse the signing credential.

  4. Synchronous signature in the hot path. Separate generation and signing into stages, or sign in the same worker with cached credentials.

Corrected model: producer partitions the 25k records into chunks; a bounded executor (e.g., 6 workers/node) each owns its client and streams PDFs to storage; signing uses a cached credential; backpressure via a bounded queue prevents heap growth; monitor GC and queue depth. Expected throughput scales with workers and removes keystore I/O.

2. The team wants to raise the heap to 32 GB to 'fix' the timeouts. Assess this and list the tuning/observability changes you would make instead.

Read the worked answer

Raising heap to 32 GB is a poor first move: it delays GC, increases pause times, and masks the leak - 25k accumulated PDFs will still exhaust any heap. It also risks exceeding container limits and causing OOM kills.

Instead:

  • Fix retention: stream results, close Document objects, avoid holding per-record state.
  • Bound concurrency to CPU count; use a bounded queue for backpressure.
  • Cache the keystore and any compiled template artifacts; reuse FormsServiceClient per worker.
  • Tune GC for the workload (e.g., G1 with a target pause, or region sizing) and set -XX:+HeapDumpOnOutOfMemoryError.
  • Observability: expose metrics for queue depth, active workers, PDFs/min, GC pause, and per-record latency; alert on timeout rate.
  • Timeout policy: raise the 60 s timeout only after fixing the leak, and make it per-stage (generation vs. signing).

Validate with a 1,000-record canary before the full run.