← Back to list

5 JavaScript Cron Jobs That Run My Freelance Business

Invoices, reports, and client updates — all automated while I actually work on code.

Huzair Awan in JavaScript in Plain English · 2026-07-06 10:54 · 0 claps · 3.1 min read paywalled
#javascript #javascript-tips #cronjob #javascript-development #javascript-frameworks
Open on Medium ↗
Wiki topics: 🌐 · Web Development

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