# PDF generation from HTML without managing servers

# 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:

```javascript
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 `/tmp` cleanup (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.

```bash
curl -X POST https://pagebolt.dev/api/v1/pdf \
  -H "x-api-key: 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

```javascript
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

```javascript
const axios = require('axios');

app.post('/invoice/:invoiceId', async (req, res) => {
  try {
    const response = await axios.post(
      'https://pagebolt.dev/api/v1/pdf',
      {
        html: req.body.html,
        format: 'A4',
        margin: '1in'
      },
      {
        headers: {
          'x-api-key': `${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.

```javascript
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://pagebolt.dev/api/v1/pdf',
    { html: htmlTemplate, format: 'A4' },
    {
      headers: { 'x-api-key': `${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

1. **Sign up** at [pagebolt.dev](https://pagebolt.dev) (free: 100 requests/month)
2. **Get API key** (1 minute)
3. **Make first PDF** (5 minutes)
4. **Evaluate**: Does it solve your use case?

No more hanging processes. No more 3 AM PDF generation failures.

[Start free](https://pagebolt.dev) — 100 PDFs/month, no credit card.
