goparsec

The library › Pipelines and automation

Pipelines and automation

Photo book generator

A rendering pipeline that turns each customer’s design into a print-ready book, cover, dust jacket and gift prints, on a server that wakes only when orders are waiting.

IThe problem

A photo book company let customers design their books online: pick a layout, drop in photos, add backgrounds, stickers and captions. Every finished design then had to become files a print shop would accept, page by page at the exact book size with bleed, plus a cover.

And a book is more than its pages. The print floor also needed a dust jacket, free gift prints, a worksheet and an invoice for every order. Orders arrive in bursts, so keeping big render servers running all day would waste money.

IIWhat I did

  1. A server that wakes up for work. A cron job runs a PDF controller that checks the order queue in Redis. When orders are waiting, it boots the PDF server, waits until it is fully up, then hands each order ID to the PDF worker.
  2. Pages rendered one by one. The generator sets the book size and bleed, reads each page of the project from Redis and S3, draws it into the PDF with iText, and repeats until the last page.
  3. Every layer in order. Background image or colour first, then SVG stickers through Apache Batik, then layout photos and free photos with their orientation corrected, then text with its font, size, colour and alignment.
  4. Everything the print floor needs. Beside the pages, content block and cover, small programs make worksheet images, a dust jacket from the book’s own photos, free gift prints cropped by a Go smart-crop tool using Google Cloud, and the invoice with its worksheet.
  5. Measured, not guessed. I benchmarked a single page step by step to see exactly where the time goes.

IIIHow it runs

Two servers share the work. A small, always-on controller watches for orders; the heavy PDF server only runs when there is something to print.

  1. Cron jobRuns the PDF controller on a schedule.
  2. PDF controllerChecks the order queue in Redis. If orders are waiting, it boots the PDF server.
  3. PDF server wakesOnce it is fully up, the controller sends each order ID to the worker.
  4. PDF worker · pdf.shAlways listening. Renders the book page by page: pages, the merged content block, the cover.
  • doWorksheetTurns the PDF into images for the print worksheet.
  • doDustJacketBuilds the dust jacket from the book’s own photos.
  • doFreeGiftMakes the free gift prints. Photos cropped by gosmartcrop, a Go tool using Google Cloud smart crop.
  • pdfInvoiceAndWorksheetProduces the invoice and the worksheet PDFs.

Everything lands in output/<project-id>/

  • Redis order queue, pages, layouts, stickers, fonts
  • AWS S3 photos, backgrounds, stickers, finished PDFs
  • AWS RDS order data

IVHow a page is built

Every page is read from Redis and S3 and built up in five layers, bottom to top. The book size and bleed are set before the first page.

  1. 1. TextFont, size, colour and alignment, exactly as designed.
  2. 2. Free photosPlaced anywhere by the customer, at their x, y, width and height.
  3. 3. Layout photosPlaced in the layout’s frames; orientation corrected first.
  4. 4. StickersSVG artwork, drawn into the page with Apache Batik.
  5. 5. BackgroundAn image from S3, or a flat colour set with iText.

VWhere the time goes

The test page held one layout photo, one sticker, one picture and one line of text. Building the PDF was never the slow part: embedding an object took 18 ms. The time went into photo work, and landscape photos cost far more than portrait ones. Filtering took 6.48 s for a landscape photo against 0.94 s for a portrait one.

Landscape photoPortrait photoSame for any photo
  • Retrieve data from RDS328 ms
  • Download object from S31.03 s
  • Output the object from S3326 ms
  • Photo orientation2.71 s2.65 s
  • Photo resize1.22 s711 ms
  • Opacity and blur to PNG3.21 s445 ms
  • Photo filter6.48 s935 ms
  • Sticker: SVG to PNG883 ms
  • Embed object in the PDF18 ms
  • Upload PDF to S32.90 s
  • Clean up storage44 ms
See the numbers as a table
StepLandscapePortrait
Retrieve data from RDS328 mssame
Download object from S31.03 ssame
Output the object from S3326 mssame
Photo orientation2.71 s2.65 s
Photo resize1.22 s711 ms
Opacity and blur to PNG3.21 s445 ms
Photo filter6.48 s935 ms
Sticker: SVG to PNG883 mssame
Embed object in the PDF18 mssame
Upload PDF to S32.90 ssame
Clean up storage44 mssame

VIScreen proof

The book editor: a sepia filter set in the editor (left) and the same photo rendered by the generator (preview). Client photos blurred.
The book editor: a sepia filter set in the editor (left) and the same photo rendered by the generator (preview). Client photos blurred.
The programs on the PDF server: one script per print product
The programs on the PDF server: one script per print product
Output folders: gift prints, invoices and worksheets, finished books
Output folders: gift prints, invoices and worksheets, finished books
My flowchart for rendering a book, page by page
My flowchart for rendering a book, page by page
The step-by-step benchmark for one page
The step-by-step benchmark for one page

Client names, server addresses and customer data are hidden. Clients stay confidential.

VIIWhere it ended

Each order becomes a complete print package automatically: pages, cover, dust jacket, gift prints, worksheet and invoice, filed under its project ID. Nobody lays out a page by hand, and the render server only runs when there is work in the queue.

The generator ran in production from 2018 to 2025, turning out the company’s books for seven years. When the company later replaced its book editor, this pipeline stayed on: it kept producing the invoice and worksheet for every order.

  • Java
  • iText
  • Apache Batik
  • Go
  • Redis
  • AWS S3
  • AWS RDS
  • Google Cloud
  • Shell
Request card · goparsec library

Got a job like this?

Describe the problem and get a quote within 24 hours.

Fill in a request card →