Schedule Daily Late Night Tasks at 11 PM | CronBase
0 23 * * * Every day at eleven o'clock in the evening.
The `0 23 * * *` cron expression schedules a job to run every single day at exactly 11:00 PM (23:00) in the system's local timezone. It is commonly used for executing late-night data synchronization, daily database backups, log rotation preparations, and system maintenance tasks before the date rolls over to the next calendar day.
- Minute
- 0
- Hour
- 23
- Day of Month
- *
- Month
- *
- Day of Week
- *
Next 5 Runs
- in 2h 21m
- in 1d 2h
- in 2d 2h
- in 3d 2h
- in 4d 2h
* Tools
Code & Implementations
#!/usr/bin/env bash
# Production Bash Cron Job Wrapper
# Scheduled via: 0 23 * * * /path/to/script.sh
set -euo pipefail
LOCKFILE="/var/lock/daily_cleanup.lock"
exec 200>"$LOCKFILE"
# Acquire an exclusive lock without blocking
if ! flock -n 200; then
echo "Error: Another instance of this late-night job is already running." >&2
exit 1
fi
echo "[$(date -u)] Starting daily maintenance tasks..."
# Real task execution here
# /usr/local/bin/cleanup-database-logs
echo "[$(date -u)] Daily maintenance completed successfully." › Setup notes
Save the script to /usr/local/bin/daily_cleanup.sh, make it executable with chmod +x, and add the entry 0 23 * * * /usr/local/bin/daily_cleanup.sh to your system crontab using crontab -e.
// cron-job.js
// Requires: npm install node-cron
const cron = require('node-cron');
const { exec } = require('child_process');
console.log('Initializing late-night daily cron scheduler...');
// Schedule task to run daily at 23:00 (11:00 PM)
cron.schedule('0 23 * * *', () => {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] Starting daily database backup transaction...`);
exec('/usr/local/bin/backup-db.sh', (error, stdout, stderr) => {
if (error) {
console.error(`[${timestamp}] Backup failed: ${error.message}`);
return;
}
if (stderr) {
console.warn(`[${timestamp}] Backup warning: ${stderr}`);
}
console.log(`[${timestamp}] Backup completed: ${stdout}`);
});
}, {
scheduled: true,
timezone: "UTC"
}); › Setup notes
Install the required package node-cron using npm, then run this file as a background daemon using a process manager like PM2: pm2 start cron-job.js --name daily-cron.
# scheduler.py
# Requires: pip install apscheduler
import sys
import logging
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def execute_nightly_sync():
logging.info("Starting scheduled nightly data synchronization pipeline...")
try:
# Place actual production database/API logic here
pass
logging.info("Nightly synchronization pipeline completed successfully.")
except Exception as e:
logging.error(f"Execution failed: {str(e)}", exc_info=True)
if __name__ == '__main__':
scheduler = BlockingScheduler()
# 0 23 * * * corresponds to hour=23, minute=0
trigger = CronTrigger(hour=23, minute=0, timezone='UTC')
scheduler.add_job(execute_nightly_sync, trigger=trigger, id='nightly_sync_job')
logging.info("Starting scheduler daemon for daily 23:00 task...")
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logging.info("Scheduler shutdown requested.")
sys.exit(0) › Setup notes
Install the APScheduler dependency with pip install apscheduler and run the script with python scheduler.py. This script runs as a blocking process ideal for Docker containers.
package main
import (
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/robfig/cron/v3"
)
func main() {
log.Println("Initializing daily 23:00 cron runner...")
// Use UTC timezone for predictable production scheduling
c := cron.New(cron.WithLocation(time.UTC))
_, err := c.AddFunc("0 23 * * *", func() {
log.Println("Starting scheduled daily cleanup process...")
err := runCleanupTask()
if err != nil {
log.Printf("ERROR: Cleanup task failed: %v", err)
} else {
log.Println("SUCCESS: Cleanup task finished.")
}
})
if err != nil {
log.Fatalf("Failed to schedule cron job: %v", err)
}
c.Start()
defer c.Stop()
// Keep process running until interrupted
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
log.Println("Shutting down cron runner gracefully...")
}
func runCleanupTask() error {
// Simulated production logic
time.Sleep(5 * time.Second)
return nil
} › Setup notes
Initialize a Go module, pull the v3 cron package with go get github.com/robfig/cron/v3, compile the code using go build, and run the resulting binary.
package com.example.scheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class NightlyTaskScheduler {
private static final Logger logger = LoggerFactory.getLogger(NightlyTaskScheduler.class);
// Spring's schedule uses 6 fields (second, minute, hour, day, month, day-of-week).
// "0 0 23 * * *" translates to 23:00:00 daily.
@Scheduled(cron = "0 0 23 * * *", zone = "UTC")
public void executeNightlyDatabaseMaintenance() {
logger.info("Triggering nightly database index maintenance job...");
try {
performMaintenance();
logger.info("Nightly database maintenance completed successfully.");
} catch (Exception e) {
logger.error("Critical error during nightly database maintenance: ", e);
// Implement alerting/monitoring notification mechanism here
}
}
private void performMaintenance() throws Exception {
// Simulate production database optimization work
Thread.sleep(10000);
}
} › Setup notes
Ensure @EnableScheduling is added to your main Spring Boot Application class. Place this class in your component scan path to let Spring automatically detect and register the scheduler.
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-reporting-pipeline
namespace: production
spec:
schedule: "0 23 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
startingDeadlineSeconds: 600
jobTemplate:
spec:
template:
spec:
containers:
- name: pipeline-runner
image: registry.example.com/data/pipeline-runner:v1.2.0
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: "500m"
memory: 512Mi
env:
- name: ENVIRONMENT
value: "production"
restartPolicy: OnFailure › Setup notes
Save this YAML manifest to a file named cronjob.yaml and apply it to your Kubernetes cluster using kubectl apply -f cronjob.yaml within the production namespace.
Last verified:
Monitor this schedule in production
Get alerted the moment this cron job fails, is late, or doesn't run. BetterStack tracks execution, duration, and output — no infrastructure required.
Platform Equivalents
AWS EventBridge
Standard cron expressions often need conversion for AWS EventBridge schedules.
cron(0 23 * * ? *) Systemd Timer
OnCalendar*-*-* 23:00:00
[Unit]
Description=Timer for cron expression: 0 23 * * *
[Timer]
OnCalendar=*-*-* 23:00:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
Why should I schedule backups at 23:00 instead of midnight?
Scheduling at 23:00 avoids the massive peak in resource utilization that typically occurs at midnight (00:00) when many automated system scripts, log rotators, and cron jobs default to run. This staggered approach ensures better CPU, memory, and network I/O availability.
How does Daylight Saving Time affect a job scheduled for 23:00?
In almost all timezones, Daylight Saving Time (DST) transitions occur at 01:00, 02:00, or 03:00. Because 23:00 is well outside of these transition windows, your job will execute reliably once per day, though the absolute UTC time of execution will shift by one hour.
What is the best way to handle long-running jobs that start at 23:00?
Ensure your scripts implement file-locking mechanisms (like `flock` in Bash) or database locks to prevent a stalled execution from overlapping with the next day's run. Additionally, set strict execution timeouts and configure monitoring alerts to notify you if the process runs past 3 hours.
How can I stagger this job across multiple servers to prevent API rate limits?
Instead of running exactly at 23:00:00 on all nodes, introduce a sleep interval or randomized jitter at the start of your script (e.g., `sleep $((RANDOM % 300))`). This spreads the network traffic and API requests over a five-minute window.
Can I use standard cron to run this only on weekdays at 23:00?
Yes, you can modify the fifth field of the cron expression. Changing the expression to `0 23 * * 1-5` will restrict the execution to Monday through Friday at 11:00 PM, skipping Saturday and Sunday.
* Explore
Related expressions you might need
Last verified: