PDF generation from HTML without managing servers
Your app generates invoices. Estimates. Contracts. Shipping labels. Every document becomes a PDF.
Currently: You run wkhtmltopdf on your server. It works... until it doesn't.
Wednesday 3 PM: wkhtmltopdf process hangs on a malformed HTML file. All PDF generation freezes. Customers can't download invoices. Support tickets pile up. By 5 PM, you're SSH'ing into production servers, killing processes manually.
There's a better way. A REST API that generates PDFs from HTML. No server to manage. No hanging processes. No complexity.
The self-hosted PDF generation trap
Most developers start with wkhtmltopdf or similar CLI tools:
const { execSync } = require('child_process');
const fs = require('fs');
function generatePDF(html, filename) {
fs.writeFileSync('/tmp/input.html', html);
execSync(`wkhtmltopdf /tmp/input.html /tmp/${filename}.pdf`, {
timeout: 30000
});
const pdf = fs.readFileSync(`/tmp/${filename}.pdf`);
fs.unlinkSync(`/tmp/input.html`);
fs.unlinkSync(`/tmp/${filename}.pdf`);
return pdf;
}
Looks simple. In production: nightmare.
Hidden costs
Process management
- wkhtmltopdf hangs on malformed HTML → timeout → manual restart
- No error recovery → customers stuck waiting
- Requires
/tmpcleanup (disk space issues) - System resource limits (ulimits) need tuning
Reliability
- Font rendering differs by system setup
- Timeouts are silent failures
- Large files OOM the process
- No graceful degradation
Scaling
- Each PDF needs a new process spawn (~2 seconds)
- Can't run 100 PDFs/second
- Vertical scaling hits ceiling
Real cost
- Server overhead: $50-100/month
- DevOps time (process management): 3-5 hours/month
- Support burden (timeouts, stuck downloads): high
- Total: $500-1,000/month in effective cost
Solution: Hosted PDF API
Call an endpoint. Get a PDF back. That's it.
curl -X POST https://api.pagebolt.dev/generate_pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #12345</h1><p>Total: $99.99</p>",
"format": "A4",
"margin": "1in"
}'
# Response: PDF binary
No infrastructure. No process management. No timeouts.
Before and after
Self-hosted approach
const express = require('express');
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
app.post('/invoice/:invoiceId', (req, res) => {
try {
const html = req.body.html;
const filename = `invoice-${req.params.invoiceId}`;
const tmpInput = path.join('/tmp', `${filename}.html`);
const tmpOutput = path.join('/tmp', `${filename}.pdf`);
fs.writeFileSync(tmpInput, html);
// This can hang, timeout, or fail silently
execSync(`wkhtmltopdf --margin-top 10 --margin-bottom 10 ${tmpInput} ${tmpOutput}`, {
timeout: 30000,
stdio: 'pipe'
});
const pdf = fs.readFileSync(tmpOutput);
// Cleanup
fs.unlinkSync(tmpInput);
fs.unlinkSync(tmpOutput);
res.set('Content-Type', 'application/pdf');
res.set('Content-Disposition', `attachment; filename="${filename}.pdf"`);
res.send(pdf);
} catch (error) {
console.error('PDF generation failed:', error);
res.status(500).send('PDF generation failed');
}
});
Cost: $50-100/month infrastructure + 3-5 hours DevOps = ~$700/month effective.
Hosted API approach
const axios = require('axios');
app.post('/invoice/:invoiceId', async (req, res) => {
try {
const response = await axios.post(
'https://api.pagebolt.dev/generate_pdf',
{
html: req.body.html,
format: 'A4',
margin: '1in'
},
{
headers: {
'Authorization': `Bearer ${process.env.PAGEBOLT_API_KEY}`,
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
}
);
res.set('Content-Type', 'application/pdf');
res.set('Content-Disposition', `attachment; filename="invoice-${req.params.invoiceId}.pdf"`);
res.send(response.data);
} catch (error) {
res.status(500).send('PDF generation failed');
}
});
Cost: $29/month (Starter, 5,000 PDFs/month), $0 infrastructure, $0 DevOps = $29/month total.
Real example: Invoice generation + email
E-commerce platform: generate invoice PDF, email to customer, archive to S3.
const axios = require('axios');
const nodemailer = require('nodemailer');
const AWS = require('aws-sdk');
async function generateAndEmailInvoice(order) {
const htmlTemplate = `
<h1>Invoice</h1>
<p>Order ID: ${order.id}</p>
<table>
${order.items.map(item => `
<tr>
<td>${item.name}</td>
<td>$${item.price}</td>
</tr>
`).join('')}
</table>
<p>Total: $${order.total}</p>
`;
// Generate PDF
const pdfResponse = await axios.post(
'https://api.pagebolt.dev/generate_pdf',
{ html: htmlTemplate, format: 'A4' },
{
headers: { 'Authorization': `Bearer ${process.env.PAGEBOLT_API_KEY}` },
responseType: 'arraybuffer'
}
);
const pdf = pdfResponse.data;
// Email to customer
const mailOptions = {
from: 'noreply@mystore.com',
to: order.customer.email,
subject: `Invoice for Order #${order.id}`,
text: 'Your invoice is attached.',
attachments: [{
filename: `invoice-${order.id}.pdf`,
content: pdf
}]
};
await nodemailer.createTransport({...}).sendMail(mailOptions);
// Archive to S3
const s3 = new AWS.S3();
await s3.putObject({
Bucket: 'invoices-archive',
Key: `${order.id}.pdf`,
Body: pdf
}).promise();
return { success: true, invoiceId: order.id };
}
Simple, reliable, no process management.
Comparison: wkhtmltopdf vs hosted API
| Factor | wkhtmltopdf | Hosted API |
|---|---|---|
| Setup | 1-2 hours | 10 minutes |
| Infra cost | $50-100/month | $0 |
| DevOps time | 3-5 hours/month | 0 hours |
| Latency | 2-5 seconds | 1-2 seconds |
| Reliability | 99% (hangs, timeouts) | 99.9% SLA |
| Scaling | Capped at server | Unlimited |
| Font support | System-dependent | Consistent |
| Custom styling | Limited | Full CSS3 |
| Per-PDF cost | $0.05-0.10 (infra) | $0.02-0.05 (API) |
When to use hosted PDF API
✅ User-facing invoice/receipt generation
✅ Automated document pipelines
✅ Report generation at scale
✅ Limited DevOps resources
✅ Unpredictable volume
Keep wkhtmltopdf if:
- You process 10,000+ PDFs/day (break-even at scale)
- You have dedicated DevOps
- Documents have extreme customization
For most: hosted wins.
Getting started
- Sign up at pagebolt.dev (free: 100 requests/month)
- Get API key (1 minute)
- Make first PDF (5 minutes)
- Evaluate: Does it solve your use case?
No more hanging processes. No more 3 AM PDF generation failures.
Start free — 100 PDFs/month, no credit card.
Top comments (0)