Generating PDFs in Next.js Without Puppeteer
Why running Puppeteer in your Next.js app is a bad idea, and how to use an API-based approach for faster, more reliable PDF generation.
The problem with Puppeteer in Next.js
If you're building a Next.js app and need to generate PDFs, your first instinct might be to reach for Puppeteer. Here's why that's usually a bad idea:
Serverless deployment (Vercel, Netlify)
Puppeteer requires a Chromium binary. On Vercel, the function bundle limit is 50MB (compressed). Chromium is 130MB compressed. It literally doesn't fit. You can use @sparticuz/chromium for a stripped-down version, but it's fragile, slow to cold-start, and adds significant complexity.
API routes aren't designed for long-running processes
Vercel functions timeout after 10-60 seconds depending on your plan. Launching Chromium, rendering a page, and generating a PDF can easily exceed that — especially under load.
Memory limits
Serverless functions typically have 1-3GB of memory. Chromium alone needs 200-400MB. Your actual application code gets whatever's left.
The solution: API-based generation
Instead of running a browser in your Next.js API route, call pdfRelay:
// app/api/generate-invoice/route.ts
export async function POST(request: Request) {
const { invoiceData } = await request.json();
const response = await fetch('https://pdfrelay.com/api/v1/convert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PDFRELAY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
source: 'html',
content: renderInvoiceHTML(invoiceData),
}),
});
const pdf = await response.arrayBuffer();
return new Response(pdf, {
headers: { 'Content-Type': 'application/pdf' },
});
}
This works on Vercel, Netlify, Cloudflare, or any hosting. No Chromium, no memory issues, no timeouts. Just standard HTML that your Rust-powered PDF engine converts in milliseconds.