5 JavaScript Cron Jobs That Run My Freelance Business
Invoices, reports, and client updates — all automated while I actually work on code.
5 JavaScript Cron Jobs That Run My Freelance Business
Invoices, reports, and client updates — all automated while I actually work on code.

You know that sinking feeling when it’s the 1st and you haven’t sent invoices? Or when a client asks for a report and you spend 3 hours pulling data from 5 platforms? I’ve been there.
Before automation, I was burning 10 hours a week on admin — non‑billable, soul‑crushing admin. Then I wrote five cron jobs that changed everything.
Here they are — short and sweet.
1. Monthly Invoice Generator
Runs on the 1st at 9 AM
The core: fetch your time entries from Toggl/Harvest, calculate totals, generate a PDF/HTML invoice, and email it.
javascript
const cron = require('node-cron');
const { fetchTimeEntries, generateInvoice, sendEmail } = require('./invoice-helper');
cron.schedule('0 9 1 * *', async () => {
const start = new Date(new Date().getFullYear(), new Date().getMonth() - 1, 1);
const end = new Date(new Date().getFullYear(), new Date().getMonth(), 0);
const entries = await fetchTimeEntries(start, end);
// Group by client
const clients = groupByClient(entries);
for (const [client, hours] of Object.entries(clients)) {
if (hours === 0) continue;
const invoice = generateInvoice(client, hours, 85); // $85/hr
await sendEmail(client.email, invoice);
}
});
Why it matters: I get paid 2 weeks faster because invoices arrive like clockwork.
2. Weekly Client Report
Runs every Friday at 4 PM
Pull commits from GitHub, completed tasks from Notion, and hours logged — then send a beautiful PDF report.
javascript
cron.schedule('0 16 * * 5', async () => {
const clients = await getClients();
for (const client of clients) {
const commits = await getCommits(client.repo, 7);
const tasks = await getCompletedTasks(client.notionDb, 7);
const hours = await getWeeklyHours(client.togglId);
const pdf = await buildPDF({ client, commits, tasks, hours });
await sendEmail(client.email, 'Weekly Report', pdf);
}
});
Why clients love it: They never have to ask “what did you do?” again. The report just shows up.
3. Daily Backup
Runs every day at 2 AM
Dump your PostgreSQL/MongoDB databases, compress them, upload to S3, and keep only the last 30 days.
javascript
cron.schedule('0 2 * * *', async () => {
const projects = getProjects();
for (const p of projects) {
const dump = p.type === 'postgres'
? await pgDump(p)
: await mongoDump(p);
await uploadToS3(dump, `daily/${p.name}-${Date.now()}.sql.gz`);
}
await cleanOldBackups(30); // keep 30 days
});
Why this saved my business: A client’s DB corrupted on a Friday. Restored from Sunday’s backup before they even noticed.
4. Lead Scraper
Runs every day at 6 AM
Scrape Upwork/Freelancer for new gigs matching your skills, filter duplicates, and push to Notion.
javascript
cron.schedule('0 6 * * *', async () => {
const keywords = ['python', 'react', 'full stack'];
const leads = [];
for (const kw of keywords) {
const fromUpwork = await scrapeUpwork(kw);
const fromFreelancer = await scrapeFreelancer(kw);
leads.push(...fromUpwork, ...fromFreelancer);
}
for (const lead of leads) {
if (!await isDuplicate(lead.title)) {
await addToNotion(lead);
}
}
await sendDigest(leads.length);
});
Real impact: I went from spending 1 hour/day browsing to 15 minutes reviewing pre‑filtered leads. Response time dropped, hire rate tripled.
5. Payment Tracker
Runs twice daily (midnight and 9 AM)
Check for upcoming retainer renewals, overdue invoices, and failed Stripe payments — then remind you before they become problems.
javascript
cron.schedule('0 0,9 * * *', async () => {
const renewals = await getUpcomingRenewals(30); // next 30 days
for (const r of renewals) sendReminder('renewal', r);
const overdue = await getOverdueInvoices();
for (const inv of overdue) sendReminder('overdue', inv);
const failed = await getFailedStripePayments();
for (const p of failed) sendReminder('failed_payment', p);
});
I stopped missing renewals: That mistake cost me $2,400 once. Not anymore.
The Deployment Setup
All five jobs live in a single cron-runner.js file. I run it on a $6/month VPS with PM2:
bash
pm2 start cron-runner.js --name freelance-bot
pm2 save
pm2 startup
The Bottom Line
These five cron jobs save me 10 hours a week — that’s ~40 hours a month. At $85/hour, that’s $3,400/month of recovered time. Plus my clients are happier, payments come faster, and I never panic about backups.
The code above is the skeleton. You’ll need to plug in your own APIs (Toggl, GitHub, Notion, Stripe, etc.) and write the helper functions. But the pattern is universal.
If you want the full, copy‑paste‑ready version with all the error handling and email templates, [drop a comment or DM me] and I’ll share the gist.
Automation isn’t lazy — it’s how you scale yourself without scaling your stress. Go build it.
P.S. — Which job would save you the most time? I’d start with invoice generation — it’s the easiest win.
메타데이터
- post_id
- 09ca5386097c
- slug
- 5-javascript-cron-jobs-that-run-my-freelance-business-09ca5386097c
- url
- https://javascript.plainenglish.io/5-javascript-cron-jobs-that-run-my-freelance-business-09ca5386097c
- canonical_url
- https://javascript.plainenglish.io/5-javascript-cron-jobs-that-run-my-freelance-business-09ca5386097c
- author_url
- https://medium.com/@huzairawan
- status
- ok
- fetched_at
- 2026-07-07 20:18:40