SnapPDFSnapPDF
← back to showcase
EXAMPLE BUILD — illustrative architecture, not a published case study

Heron Neobank

Monthly statements for 2M accounts without a Puppeteer cluster.

Neobank · Series C · 140 engineers

The build

Consumer neobank generating 2M statements/month. Replaced 40-node Puppeteer cluster with SnapPDF Enterprise. SOC 2 auditor signed off cleanly.

Stack

  • · Kotlin
  • · GCP
  • · Kafka
  • · Kubernetes
  • · SnapPDF Enterprise

Architecture

your app/mergeSnapPDF/watermarkSnapPDF/protectSnapPDF/metadataSnapPDFdelivery

Ops used: /merge → /watermark → /protect → /metadata

How they use SnapPDF

Heron Neobank serves 2M US consumers. Monthly statements go out on the 1st, quarterly tax forms on April 1 / Jan 31 — the pipeline must handle 2M PDFs in a 4-hour window without errors a regulator could cite.

The pre-SnapPDF stack: 40× c5.xlarge GCE instances running a custom Puppeteer-based renderer. Memory leaks caused weekly pod restarts. The ops team had a runbook titled "Statement Day" with 17 steps. A SOC 2 auditor flagged three findings related to the statement pipeline in the 2025 audit cycle.

The migration was staged over 12 weeks. Phase 1: shadow-mode, where both pipelines ran and outputs were byte-compared (allowing for acceptable timestamp drift). Phase 2: canary at 1% of customers. Phase 3: full cutover. Phase 4: decommission the Puppeteer cluster.

The new pipeline: each statement is rendered to page-PDFs from their Kotlin core-banking engine, SnapPDF merges them with the fee schedule + Reg E disclosure, watermark stamps the account's last-four for anti-fraud correlation, protect locks with AES-256 per-customer owner-password, metadata embeds SHA-256 hash + statement_id for audit reconciliation. The audit event goes to Kafka → their SIEM.

Measured: infrastructure cost for PDF generation fell from $456k/year to $0 (SnapPDF Enterprise absorbed). Engineering ownership fell from 2 FTE to 0.2 FTE. The 2026 SOC 2 audit had zero findings in the statement pipeline section; the auditor specifically noted the SHA-256-in-metadata pattern as an exemplar control.

The quiet win: the "Statement Day" runbook is gone. Monthly statements ship and nobody notices. Heron's VP Platform called it "the only migration that left no fingerprint."

Outcomes

Infra cost
$456k → $0 (absorbed)
SOC 2 findings
3 → 0
Statements/month
2,000,000
Eng ownership
2 FTE → 0.2 FTE

Integration pattern

A simplified excerpt showing the core SnapPDF calls.

// heron-core/src/statement/StatementIssuer.kt
class StatementIssuer(
    private val snap: SnapPDFClient,
    private val vault: OwnerPasswordVault,
    private val auditLog: KafkaProducer<String, AuditEvent>,
) {
    suspend fun issue(account: Account, month: YearMonth): ByteArray {
        val pages = renderStatementPages(account, month)

        val merged = snap.merge(
            MergeRequest(files = pages + listOf(FEE_SCHEDULE_URL, REG_E_URL))
        )
        val stamped = snap.watermark(
            WatermarkRequest(
                file = merged.pdf, kind = "text",
                text = "ACCT ${account.lastFour}",
                position = "bottom-center", opacity = 0.1
            )
        )
        val locked = snap.protect(
            ProtectRequest(
                file = stamped.pdf,
                ownerPassword = vault.key(account.id),
                encryption = "aes-256",
                permissions = Permissions(
                    printing = "high-res", copying = false, modifying = false
                )
            )
        )

        val hash = sha256(locked.pdf)
        val final = snap.setMetadata(
            SetMetadataRequest(
                file = locked.pdf,
                metadata = mapOf(
                    "title" to "Statement ${account.number} $month",
                    "subject" to "SHA256:$hash",
                    "keywords" to listOf("statement", account.id, month.toString())
                )
            )
        )

        auditLog.send("statement.issued", AuditEvent(account.id, month, hash))
        return final.pdf
    }
}

Start building like this

Free tier gives you 100 ops/month — enough to prototype any of the flows on this page. No card required.

Other builds