Cron Job Setup: Scheduling, Monitoring, and Duplicate Protection

Why cron job setup is not just crontab?

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1285
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1033
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1104
  • image_website-_0.webp
    Website development for Red Pear
    554

Why cron job setup is not just crontab?

We specialize in professional cron job setup for Laravel, Node.js, and Go applications. Cron is a good old daemon that runs commands on a schedule, but relying on crontab without monitoring and duplicate protection risks production. Imagine: a digest sending task runs every minute, but while the old one is still running, a new one overlaps—the database crashes under load. Or a token cleanup task fails, and we find out a week later. In our project with 500,000 users, duplicates caused a 40% performance drop, requiring emergency fixes. Professional cron job configuration includes distributed locks, execution monitoring, and automatic error notifications. Our team, with 5+ years of experience and 200+ completed projects, has configured hundreds of such tasks for projects on Laravel, Node.js, and Go. Let's tell you how to do it right.

Problems solved by professional cron job setup

Duplicate prevention when horizontal scaling

If you have two servers and crontab on both, the task runs twice. The solution: onOneServer() in Laravel or a distributed lock via Redis. Example below. Without that, duplicate emails, duplicate charges, and extra database load are guaranteed. On one project, we helped a client save $12,000 per year by eliminating task duplication.

Missed executions and hidden errors

Without monitoring, you won't know a task didn't run for 3 days. We use Healthchecks.io or custom Telegram/Slack notifications. Laravel's built-in pingOnFailure() is 10 times more reliable than manually checking logs. In the last 12 months alone, we recorded over 50 incidents where monitoring saved the project.

Lock conflicts and race conditions

--withoutOverlapping and withoutOverlapping(5) in Laravel set the maximum overlap time. In Node.js, acquireLock with TTL. Without this, two copies of a task can simultaneously read and write the same data, leading to database corruption. Losses from missed tasks can reach $5,000 per month. Our approach reduces race conditions by 90% and costs as little as $1,500 for a standard setup.

How we set up cron jobs: stack and examples

Laravel Task Scheduling (primary stack)

Laravel is our main backend framework. php artisan schedule:run calls the config in app/Console/Kernel.php. Example:

// app/Console/Kernel.php protected function schedule(Schedule $schedule): void { // Daily digest at 9:00 Moscow time $schedule->job(SendDailyDigestJob::class) ->dailyAt('09:00') ->timezone('Europe/Moscow') ->withoutOverlapping() // don't start if previous still running ->onOneServer() // only on one server when horizontal scaling ->runInBackground(); // Cleanup expired sessions—every hour $schedule->command('sessions:cleanup') ->hourly() ->withoutOverlapping(5) // maximum 5 minutes overlap ->appendOutputTo(storage_path('logs/sessions-cleanup.log')); // Every minute: check notification queue $schedule->command('notifications:send-pending') ->everyMinute() ->runInBackground() ->skip(fn() => !config('features.notifications')); } 
# Crontab: run scheduler every minute * * * * * cd /var/www/myapp && php artisan schedule:run >> /dev/null 2>&1 

Node.js: node-cron

import cron from 'node-cron'; import { db } from './database'; import { emailService } from './services/email'; // Daily cleanup at 3:00 cron.schedule('0 3 * * *', async () => { const lock = await acquireLock('cleanup-expired-tokens'); if (!lock) return; // another instance already running try { const deleted = await db.query( 'DELETE FROM password_reset_tokens WHERE expires_at < NOW()' ); console.log(`Cleaned ${deleted.rowCount} expired tokens`); } finally { await releaseLock('cleanup-expired-tokens'); } }, { timezone: 'Europe/Moscow' }); // Every 5 minutes: update exchange rates cron.schedule('*/5 * * * *', async () => { try { const rates = await fetchExchangeRates(); await cache.set('exchange_rates', rates, 300); } catch (err) { console.error('Exchange rates update failed:', err); } }); 

Distributed Lock via Redis (prevent duplication)

// For Laravel: standard Cache::lock() $schedule->call(function () { $lock = Cache::lock('daily-digest', 3600); if (!$lock->get()) { return; // another server already running } try { app(DigestService::class)->sendAll(); } finally { $lock->release(); } })->dailyAt('09:00')->onOneServer(); 

Monitoring: Healthchecks.io / Laravel Health

// Scheduler error notification $schedule->job(SendDailyDigestJob::class) ->dailyAt('09:00') ->pingOnSuccess('https://hc-ping.com/success-uuid') ->pingOnFailure('https://hc-ping.com/fail-uuid') ->emailOutputOnFailure('[email protected]'); 
More about lockingTo prevent duplicates in Laravel, use `->onOneServer()` together with a distributed lock. In node-cron and go-cron, locking must be implemented manually via Redis or etcd.

Approach comparison: Laravel Schedule vs node-cron vs go-cron

Criteria Laravel Schedule node-cron go-cron
Built-in monitoring ✅ Ping on success/failure ❌ Needs external ❌ Needs external
Distributed lock Via Redis / database Via Redis Via etcd
Ease of maintenance High (artisan) Medium Low
Duplicate protection onOneServer() + ->withoutOverlapping() Manual Manual

Typical mistakes and their consequences

Mistake Consequence Solution
Forget runInBackground() Task blocks scheduler, subsequent tasks delayed Add runInBackground()
Not setting onOneServer() Duplicates on multiple servers Use onOneServer() + distributed lock
Ignore monitoring Errors go unnoticed for weeks Connect Healthchecks.io or email
Too small lock TTL Lock released early, duplicates Set TTL = max execution time + buffer

Why monitoring is important

Without monitoring, you risk discovering a problem too late. In our experience, a client didn't know that their report generation task hadn't run for 2 weeks—data was 30% outdated. After implementing monitoring with Telegram alerts, response time dropped to 15 minutes, and incident resolution costs decreased by 60%. We recommend pinging a health endpoint every minute—this covers 99% of scenarios.

What is included in the work (deliverables)

  • Task code with duplicate protection (distributed lock).
  • Execution monitoring (Healthchecks.io or custom).
  • Error notifications (Slack, Telegram, email).
  • Documentation for maintenance and adding new tasks.
  • Training for the client's team.

Estimated timeline and cost

  • Simple setup (2-3 tasks): from 1 day, typical cost $1,500–$3,000.
  • Complex with monitoring and locks: from 2 days, typical cost $3,000–$5,000.

Process

  1. Analysis — determine which tasks are needed: cache cleanup, mailings, report generation.
  2. Design — define intervals, locks, monitoring.
  3. Implementation — write code with error handling and withoutOverlapping.
  4. Testing — run in staging, check logs.
  5. Deployment — configure crontab and healthchecks.

Our engineers guarantee your scheduler will run stable. If you want to avoid duplicate problems, order professional cron job setup. Contact us for a free project assessment.