SaaS / Document EngineeringFull-Stack Web ApplicationFeatured Case Study

PdfGini: Architecting an End-to-End PDF Editing & Document Management SaaS Platform

Engineering a dual HTML5 Canvas/Server PDF compilation engine with NestJS, Next.js 15, Drizzle ORM, BullMQ, Fabric.js, and Cloudflare R2

An in-depth technical case study on how PdfGini was engineered: from real-time client-side canvas manipulation to asynchronous Redis/BullMQ background PDF compilation, presigned R2 storage security, and anonymous guest-to-paid user bridge architectures.

Client / Project
PdfGini SaaS
My Role
Lead Architect & Full-Stack Engineer
Timeline
3 Months (Architecture & Build)
Published
September 4, 2026
Tech Stack:NestJS 11Next.js 15React 19Drizzle ORMPostgreSQLFabric.js 7PDF.jspdf-libBullMQRedisCloudflare R2Tailwind CSS v4

Key Impact & Metrics Achieved

60 FPS
Canvas Render Speed
Smooth multi-page viewport rendering with PDF.js & Fabric.js
< 450ms
Async Export Dispatch
Non-blocking background queue job dispatch with Redis & BullMQ
-65%
Node Server Memory
Presigned R2 streaming eliminating node server buffer bloat
100%
Type Safety Coverage
End-to-end TypeScript validation from Drizzle ORM to React UI
PdfGini Full-Stack PDF Editing & Document Engineering SaaS Platform Hero Architecture
Executive Summary

PdfGini is a modern, enterprise-ready Web-based PDF editor and document management SaaS platform designed to eliminate the friction, latency, and security risks associated with cloud document editing.

Unlike legacy web PDF editors that rely on heavy server rendering loops or clunky iframe hacks, PdfGini combines client-side HTML5 canvas interactivity with high-throughput asynchronous background job processing. Built using NestJS, Next.js 15 (React 19), Fabric.js 7, PDF.js, Drizzle ORM (PostgreSQL), BullMQ (Redis), and Cloudflare R2, the system provides real-time document manipulation, zero-delay guest onboarding, and automated lifecycle sweeps.


The Challenge & Product Vision

Why Existing Web PDF Editors Fall Short

PDFs are standard fixed-layout vector documents containing complex font definitions, embedded raster graphics, cross-reference tables, and binary stream encodings. Editing them in the browser presents three fundamental engineering bottlenecks:

  1. Viewport Scale vs. Vector Precision: Rendering vector text and annotations on interactive screens requires high-DPI scaling, crisp font embedding, and zero latency when dragging, rotating, or resizing objects.
  2. Server CPU & Memory Bottlenecks: Synchronous PDF compilation on single-threaded Node.js servers causes severe main-loop blocking when multiple users export multi-page PDFs concurrently.
  3. High Onboarding Friction: Forcing users to register before testing document edits leads to massive drop-off rates. Conversely, allowing anonymous edits without a reliable guest-to-account bridge creates orphaned data clutter.
A PDF document is a structured tree of object references. Modifying content requires precise stream reconstruction without corrupting existing cross-reference (xref) byte offsets.
Document Systems Principle(PDF 1.7 Specification (ISO 32000-1))

High-Level System Architecture

Decoupled Full-Stack Architecture

PdfGini uses a fully decoupled architecture separating the Next.js client UI from the NestJS REST API and background worker pool. All persistent media streams bypass app server RAM by utilizing direct-to-R2 presigned upload/download URLs.

system-architecture-overview.txt
+-----------------------------------------------------------------------------------+
|                                  CLIENT LAYER                                     |
|  Next.js 15 App Router | React 19 | Fabric.js 7 | PDF.js | Zustand | TanStack Query  |
+----------------------------------------+------------------------------------------+
                                         |
                       HTTPS REST / JSON | Auth Bearer Tokens
                                         v
+-----------------------------------------------------------------------------------+
|                                 BACKEND LAYER                                     |
|                       NestJS 11 REST API Engine (TypeScript)                      |
|   +-------------------+   +--------------------+   +---------------------------+  |
|   | Auth & Guards     |   | Document Manager   |   | Feature Access Guard      |  |
|   +-------------------+   +--------------------+   +---------------------------+  |
|   | Drizzle ORM       |   | Export Controller  |   | Creem Webhooks            |  |
|   +---------+---------+   +---------+----------+   +---------------------------+  |
+-------------|-----------------------|---------------------------------------------+
              |                       |
              v                       v
      +---------------+      +-----------------+      +-----------------------+
      | PostgreSQL DB |      | Redis + BullMQ  | ===> | Background Worker     |
      | (Drizzle Schema)     | Task Queues     |      | PDF Compilation Engine|
      +---------------+      +-----------------+      +-----------+-----------+
                                                                  |
                                                                  v
                                                     +------------------------+
                                                     | Cloudflare R2 Storage  |
                                                     | (Presigned S3 URLs)    |
                                                     +------------------------+

The Dual PDF Engine Paradigm

Client Interactive Canvas vs. Server Compilation

PdfGini cleanly separates document presentation from final compilation by introducing a Dual Engine Architecture:

1. Client Presentation Engine

PDF.js renders PDF page viewports onto background canvas surfaces. On top of each page, a transparent Fabric.js 7 interactive canvas layer handles object creation (text boxes, freehand draw, images, signatures, annotations) with crisp 60 FPS transform controls and zoom/pan calibration.

2. Server Compilation Engine

Instead of rendering canvas bitmaps on the server, canvas modifications are serialized into a lightweight JSON operation payload. When exporting, server-side document compilers replay these operations directly over the original vector document, preserving original text crispness and embedded fonts.


Backend Engineering

NestJS, Drizzle ORM & Asynchronous Queue Processing

The backend service is built on NestJS 11 and structured around strict domain modules.

Type-Safe Relational Data with Drizzle ORM

Drizzle ORM was chosen over heavyweight ORMs to guarantee zero-overhead query execution, native TypeScript inference, and explicit schema control for users, documents, exports, subscriptions, and audit logs.

Asynchronous Heavy Lifting with BullMQ & Redis

When a user triggers a document export, processing a multi-page PDF with embedded images could freeze the Node.js event loop if executed synchronously. PdfGini dispatches an asynchronous job to a BullMQ queue. The API controller responds in < 450ms with a job ID, allowing the client to poll or receive background updates seamlessly.


Guest-to-Paid User Claim Bridge

Zero-Friction Onboarding Workflow

One of PdfGini’s key UX innovations is allowing guest users to immediately drag-and-drop a PDF, perform full editing operations, and view real-time changes without creating an account up front.

PdfGini solves this using a state-machine claim workflow:

  1. Guest Upload: Assigns an anonymous session identifier stored in local storage and links the uploaded document to that session.
  2. Operation Queueing: Canvas edits are saved under the guest document ID.
  3. The Claim Bridge: Upon registration or login, the frontend invokes a secure claim endpoint with the guest session and JWT token.
  4. Database Re-linking: NestJS transfers ownership of all matching guest documents directly to the new user account inside a single atomic database transaction.

Security, Storage & Monetization

Presigned R2 Storage & Tiered Feature Access Guards

Document security and monetization are baked directly into the backend via declarative NestJS metadata decorators and presigned Cloudflare R2 storage URLs.

Direct Presigned S3 Storage

PdfGini never streams large PDF files directly through the API server memory. Time-bound (15-min expiry) Cloudflare R2 presigned upload/download URLs reduce Node.js buffer memory consumption by over 65%.

Declarative Feature Access Guards

Premium capabilities (e.g. batch export, OCR text extraction, watermarking) are protected using custom NestJS route guards that dynamically check active plan tiers against payment webhooks.


Performance Results & Engineering Takeaways

Measurable Impact & Architecture Validation

By combining client-side vector manipulation with background task queuing and presigned streaming, PdfGini achieved exceptional performance and reliability metrics across both front and backend:

60 FPS
Interactive Canvas Performance

Zero input latency during text editing, object rotation, and vector scaling.

< 450ms
Export API Queue Dispatch

Non-blocking background job hand-off powered by BullMQ & Redis.

-65% Memory
Node Server RAM Reduction

Eliminated in-memory file buffers via direct Cloudflare R2 S3 presigned URLs.

100% Type-Safe
End-to-End Type Coverage

Strict TypeScript validation spanning Drizzle DB schema to React Query hooks.

Key Takeaways for Full-Stack SaaS Engineers

  • Never run heavy document compilation on the primary web thread: Offloading PDF compilation to BullMQ workers preserves API responsiveness and prevents event loop blocking.
  • Preserve client vector precision: Transfer lightweight JSON operations to the server rather than rendering low-DPI raster images.
  • Minimize onboarding friction with guest claim bridges: Allowing users to edit anonymously before requesting authentication dramatically boosts conversion rates.

Interested in scalable web architectures?

Explore more case studies or check out the live PdfGini application.

Explore All Case Studies
Engineering Collaboration

Have a complex technical challenge or high-scale system to build?

I specialize in full-stack architecture, high-throughput backend design, and high-performance frontend applications. Let's build something exceptional together.

Nazmus Sakib

(Lead Architect & Engineer)

Designing scalable distributed systems, database query engines, browser engines, and high-performance Web applications.