Scheduled PDF Generation
Automate recurring PDF generation with cron jobs, task schedulers, and event-driven triggers.
Overview
Many workflows require PDFs on a schedule — monthly invoices, weekly reports, daily summaries. This guide covers common patterns for automating PDF generation.
Node.js Cron Job
Using node-cron
import cron from "node-cron";
import { DocumentStack } from "@document-stack/sdk-node";
const client = new DocumentStack({ apiKey: process.env.DS_API_KEY! });
// Run on the 1st of every month at 9 AM
cron.schedule("0 9 1 * *", async () => {
console.log("Starting monthly invoice generation...");
const customers = await db.query(
"SELECT * FROM customers WHERE billing_active = true"
);
for (const customer of customers) {
const pdf = await client.generate({
templateId: "tmpl_invoice",
data: {
customerName: customer.name,
amount: customer.monthlyCharge,
period: new Date().toLocaleDateString("en-US", {
month: "long",
year: "numeric",
}),
},
});
await sendEmail(customer.email, "Your Monthly Invoice", pdf.url);
}
console.log(`Generated ${customers.length} invoices`);
});Python Scheduler
Using APScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
from document_stack import DocumentStack
client = DocumentStack(api_key=os.environ["DS_API_KEY"])
scheduler = BlockingScheduler()
@scheduler.scheduled_job("cron", day=1, hour=9)
def generate_monthly_reports():
customers = db.get_active_customers()
for customer in customers:
pdf = client.generate(
template_id="tmpl_report",
data={
"customerName": customer.name,
"period": "January 2025",
"metrics": customer.get_monthly_metrics(),
},
)
send_email(customer.email, pdf.url)
scheduler.start()Serverless (AWS Lambda)
Lambda Handler
import { DocumentStack } from "@document-stack/sdk-node";
const client = new DocumentStack({ apiKey: process.env.DS_API_KEY! });
export const handler = async (event: any) => {
const { templateId, data, recipientEmail } = event;
const pdf = await client.generate({ templateId, data });
// Send via SES or store in S3
await sendEmail(recipientEmail, pdf.url);
return { statusCode: 200, body: JSON.stringify({ url: pdf.url }) };
};
// Trigger: CloudWatch Events rule (cron expression)
// cron(0 9 1 * ? *) — 1st of every month at 9 AM UTCCommon Schedule Patterns
| Use Case | Cron Expression | Description |
|---|---|---|
| Monthly invoices | 0 9 1 * * | 1st of month, 9 AM |
| Weekly reports | 0 8 * * 1 | Every Monday, 8 AM |
| Daily summaries | 0 18 * * * | Every day, 6 PM |
| Quarterly statements | 0 9 1 1,4,7,10 * | Jan/Apr/Jul/Oct 1st |
Time Zones
Always configure your scheduler with an explicit time zone to avoid surprises with daylight saving time.Best Practices
- Log every generation for audit trails
- Use dead letter queues for failed generations
- Set up alerts for schedule failures
- Test schedules in staging before production
- Implement idempotency — duplicate runs shouldn't create duplicate documents
Next Steps
- Batch Generation — Concurrent processing patterns
- Email Attachments — Send PDFs via email
- Webhooks — Event-driven generation