# Cron Jobs in S-UI: How Automated Background Tasks Keep Your Panel Running

> Discover S-UI cron jobs for automated tasks. Learn how S-UI uses robfig/cron for statistics, client expiration, database maintenance, and process monitoring keeping your panel running smoothly.

- Repository: [Alireza Ahmadi/s-ui](https://github.com/alireza0/s-ui)
- Tags: how-to-guide
- Published: 2026-05-22

---

**S-UI uses the robfig/cron library to execute five automated background jobs that handle statistics collection, client expiration, database maintenance, and core process monitoring.**

The S-UI panel (`alireza0/s-ui`) implements a robust background task system to ensure continuous service availability and data integrity. These cron jobs in S-UI operate automatically once the application starts, requiring no manual intervention for routine maintenance. All scheduled tasks are orchestrated through the `CronJob` struct in [`cronjob/cronJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/cronJob.go), which initializes the scheduler with the server's time zone and configured traffic retention settings.

## How the Cron Scheduler Initializes

At application startup, the `app.Start` function instantiates a `CronJob` and invokes its `Start` method. This method accepts a `*time.Location` for timezone-aware scheduling and an integer `trafficAge` that determines how many days of traffic statistics to retain.

The `CronJob` struct maintains a `*cron.Cron` instance from the `robfig/cron` library. When `Start` executes, it creates the scheduler with seconds precision and the provided location:

```go
// cronjob/cronJob.go – simplified view
func (c *CronJob) Start(loc *time.Location, trafficAge int) error {
    c.cron = cron.New(cron.WithLocation(loc), cron.WithSeconds())
    c.cron.Start()
    go func() {
        c.cron.AddJob("@every 10s", NewStatsJob(trafficAge > 0))
        c.cron.AddJob("@every 1m", NewDepleteJob())
        if trafficAge > 0 {
            c.cron.AddJob("@daily", NewDelStatsJob(trafficAge))
        }
        c.cron.AddJob("@every 5s", NewCheckCoreJob())
        c.cron.AddJob("@every 10m", NewWALCheckpointJob())
    }()
    return nil
}

```

The method registers all jobs within a goroutine and enables graceful shutdown via the `Stop` method, which halts the cron scheduler cleanly.

## The Five Automated Background Jobs

S-UI runs five distinct jobs on different schedules to maintain system health. Each job is implemented as a separate file in the `cronjob/` directory.

### StatsJob – Real-Time Statistics Collection (@every 10s)

The **StatsJob** runs every 10 seconds to capture system metrics. Located in [`cronjob/statsJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/statsJob.go), it calls `StatsService.SaveStats` to persist connection counters. If the `trafficAge` parameter is greater than zero, the job also records detailed per-client traffic data for historical analysis; otherwise, it saves only current connection statistics without persistent traffic logging.

### DepleteJob – Client Expiration Management (@every 1m)

Running every minute, the **DepleteJob** ([`cronjob/depleteJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/depleteJob.go)) enforces subscription time limits. It invokes `ClientService.DepleteClients` to disable clients whose expiration dates have passed, then triggers `InboundService.RestartInbounds` to restart only the affected inbound listeners, applying changes without disrupting active connections on unchanged ports.

### DelStatsJob – Data Retention Enforcement (@daily)

The **DelStatsJob** ([`cronjob/delStatsJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/delStatsJob.go)) executes daily at midnight, but only when `trafficAge` is configured greater than zero. This job calls `StatsService.DelOldStats` to remove statistics records older than the specified retention period, preventing unbounded database growth and maintaining query performance.

### CheckCoreJob – Process Resilience (@every 5s)

To ensure continuous proxy service availability, the **CheckCoreJob** ([`cronjob/checkCoreJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/checkCoreJob.go)) runs every five seconds. It verifies that the core V2Ray process is active and invokes `ConfigService.StartCore` to restart the process if it has crashed or stopped unexpectedly.

### WALCheckpointJob – Database Optimization (@every 10m)

Every ten minutes, the **WALCheckpointJob** ([`cronjob/WALCheckpointJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/WALCheckpointJob.go)) executes `PRAGMA wal_checkpoint(FULL)` on the SQLite database. This write-ahead log checkpoint prevents the WAL file from growing excessively large, which could otherwise degrade performance or consume excessive disk space during high-traffic periods.

## Practical Usage Examples

While the cron system starts automatically with the application, understanding the underlying API enables custom integrations and testing scenarios.

### Starting the Cron System Manually

To initialize the scheduler programmatically with a 30-day traffic retention period:

```go
package main

import (
    "time"

    "github.com/alireza0/s-ui/cronjob"
)

func main() {
    // Example: use the server's local time zone and keep traffic for 30 days
    loc, _ := time.LoadLocation("Local")
    cron := cronjob.NewCronJob()
    _ = cron.Start(loc, 30) // error handling omitted for brevity
    // The scheduler now runs in the background
    select {} // block forever (or integrate with the rest of the app)
}

```

### Manually Invoking a Job for Testing

You can execute any job synchronously for debugging or one-time maintenance:

```go
package main

import (
    "github.com/alireza0/s-ui/cronjob"
)

func main() {
    // Run the statistics job once, without persisting traffic data
    job := cronjob.NewStatsJob(false)
    job.Run() // logs any error internally
}

```

### Adjusting Traffic Retention Policies

The `trafficAge` parameter controls two behaviors simultaneously:

- **When `trafficAge > 0`**: StatsJob saves detailed traffic data, and DelStatsJob is scheduled to run daily.
- **When `trafficAge == 0`**: Traffic storage is disabled, and the daily cleanup job is omitted entirely.

```go
cron.Start(loc, 0) // disables traffic collection and old-stats cleanup

```

## Summary

- S-UI implements five automated cron jobs using the `robfig/cron` library, initialized in [`cronjob/cronJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/cronJob.go).
- **StatsJob** collects metrics every 10 seconds, with optional persistent traffic logging based on the `trafficAge` setting.
- **DepleteJob** disables expired clients and restarts affected inbounds every minute.
- **DelStatsJob** runs daily to purge old statistics when retention is enabled.
- **CheckCoreJob** ensures the V2Ray process remains active by checking every 5 seconds.
- **WALCheckpointJob** prevents SQLite WAL file bloat by running `PRAGMA wal_checkpoint(FULL)` every 10 minutes.

## Frequently Asked Questions

### What library does S-UI use for scheduling cron jobs?

S-UI uses the **robfig/cron** library with seconds-level precision and timezone support. The scheduler is configured in [`cronjob/cronJob.go`](https://github.com/alireza0/s-ui/blob/main/cronjob/cronJob.go) with `cron.WithSeconds()` and `cron.WithLocation()` to ensure accurate task execution based on the server's local time.

### How often does S-UI verify that the V2Ray core is running?

The **CheckCoreJob** runs every 5 seconds (`@every 5s`) to verify process health. If the core process has stopped, it immediately invokes `ConfigService.StartCore` to restart the service, ensuring minimal downtime for proxy connections.

### Can I disable traffic data collection to save disk space?

Yes. When initializing the cron system, set the `trafficAge` parameter to `0`. This disables the persistent storage of traffic statistics in StatsJob and prevents the **DelStatsJob** from being registered, eliminating both the storage overhead and the daily cleanup routine.

### Where are the individual job implementations located in the repository?

Each cron job resides in its own file within the `cronjob/` directory: [`statsJob.go`](https://github.com/alireza0/s-ui/blob/main/statsJob.go) for statistics collection, [`depleteJob.go`](https://github.com/alireza0/s-ui/blob/main/depleteJob.go) for client expiration, [`delStatsJob.go`](https://github.com/alireza0/s-ui/blob/main/delStatsJob.go) for data retention, [`checkCoreJob.go`](https://github.com/alireza0/s-ui/blob/main/checkCoreJob.go) for process monitoring, and [`WALCheckpointJob.go`](https://github.com/alireza0/s-ui/blob/main/WALCheckpointJob.go) for database maintenance.