# How to Schedule Automated SEO Audits with OpenSEO: Cloudflare Workers Cron Guide

> Automate SEO audits with OpenSEO using Cloudflare Workers. Schedule regular audits with a cron trigger in wrangler.toml for continuous site optimization.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: tutorial
- Published: 2026-08-21

---

**Schedule automated SEO audits with open-seo by implementing a Cloudflare Workers `scheduled` handler that invokes `AuditService.startAudit()` and configuring a cron trigger in [`wrangler.toml`](https://github.com/every-app/open-seo/blob/main/wrangler.toml) to execute the audit pipeline automatically.**

OpenSEO is an open-source SEO platform built on Cloudflare Workers that provides comprehensive site auditing capabilities. Production environments require continuous monitoring to catch SEO regressions early. This guide demonstrates how to **schedule automated SEO audits with open-seo** using native cron triggers and the platform's existing workflow architecture.

## Understanding the OpenSEO Audit Architecture

Before implementing scheduling, understand how OpenSEO executes audits. The system uses a workflow-based architecture centered on **SiteAuditWorkflow** ([[`src/server/workflows/SiteAuditWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/src/server/workflows/SiteAuditWorkflow.ts)](https://github.com/every-app/open-seo/blob/main/src/server/workflows/SiteAuditWorkflow.ts)) and **AuditService** to orchestrate crawls, Lighthouse analysis, and issue detection.

The audit process follows sequential phases defined in [[`siteAuditWorkflowPhases.ts`](https://github.com/every-app/open-seo/blob/main/siteAuditWorkflowPhases.ts)](https://github.com/every-app/open-seo/blob/main/src/server/workflows/siteAuditWorkflowPhases.ts):

- **Crawl phase**: Discovers URLs via the distributed crawler
- **Lighthouse phase**: Runs performance and SEO audits on discovered pages
- **Issue aggregation**: Compiles findings into structured reports via **AuditRepository**

When you invoke `AuditService.startAudit(projectId, options)`, the service creates an audit record and initiates the workflow, storing progress in `AuditProgressKV` until completion.

## Leveraging Cloudflare Workers Scheduled Events

OpenSEO runs on the Cloudflare Workers platform, which supports **scheduled events** (cron triggers) natively. The type definitions in [[`worker-configuration.d.ts`](https://github.com/every-app/open-seo/blob/main/worker-configuration.d.ts)](https://github.com/every-app/open-seo/blob/main/worker-configuration.d.ts) declare the `scheduled` handler interface that the runtime invokes according to your configured schedule.

The global entry point in [[`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts)](https://github.com/every-app/open-seo/blob/main/src/server.ts) currently implements a scheduled handler for rank tracking. You can extend this pattern to trigger audits by calling the same `AuditService` methods used by the interactive tools in [[`src/server/mcp/tools/site-audit-tools.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/site-audit-tools.ts)](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/site-audit-tools.ts).

## Implementation: Creating the Scheduled Audit Handler

### 1. Implement the Scheduled Handler

Create a new file that exports a `scheduled` function conforming to the Cloudflare Workers interface. This handler invokes `AuditService.startAudit()` with your target project configuration:

```typescript
// src/server/scheduled-audit.ts
import { AuditService } from "@/server/features/audit/services/AuditService";

export async function scheduled(controller: ScheduledController) {
  const projectId = process.env.AUDIT_PROJECT_ID;
  const startUrl = process.env.AUDIT_START_URL;
  
  if (!projectId || !startUrl) {
    throw new Error("Missing AUDIT_PROJECT_ID or AUDIT_START_URL environment variables");
  }

  const { auditId } = await AuditService.startAudit(projectId, {
    url: startUrl,
    maxPages: 100, // Adjust based on your site size
  });

  console.log(`Scheduled audit initiated: ${auditId} at ${new Date().toISOString()}`);
}

```

### 2. Configure the Cron Trigger

Add the schedule to your [`wrangler.toml`](https://github.com/every-app/open-seo/blob/main/wrangler.toml) configuration file. The following example runs the audit daily at 02:30 UTC:

```toml

# wrangler.toml

name = "open-seo"
main = "src/server.ts"

[triggers]
crons = ["30 2 * * *"]

```

You can specify multiple cron expressions to run audits at different frequencies for various project sizes.

### 3. Register the Handler in the Entry Point

Ensure your [[`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts)](https://github.com/every-app/open-seo/blob/main/src/server.ts) exports the scheduled handler so Cloudflare can invoke it:

```typescript
// src/server.ts
import { scheduled } from "./server/scheduled-audit";

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    // Existing fetch handler logic
  },
  
  async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext) {
    await scheduled(controller);
  },
};

```

## How the Scheduled Audit Executes

Once deployed, the execution flow follows this path:

1. **Cron invocation**: Cloudflare Workers runtime triggers the `scheduled` function at the specified interval
2. **Service initialization**: The handler calls `AuditService.startAudit()`, which validates the project and creates an audit record via **AuditRepository** ([[`src/server/features/audit/repositories/AuditRepository.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/audit/repositories/AuditRepository.ts)](https://github.com/every-app/open-seo/blob/main/src/server/features/audit/repositories/AuditRepository.ts))
3. **Workflow orchestration**: **SiteAuditWorkflow** begins execution, processing phases sequentially as defined in [[`siteAuditWorkflowPhases.ts`](https://github.com/every-app/open-seo/blob/main/siteAuditWorkflowPhases.ts)](https://github.com/every-app/open-seo/blob/main/src/server/workflows/siteAuditWorkflowPhases.ts)
4. **Progress tracking**: The workflow updates `AuditProgressKV` with crawl status and completion percentages
5. **Result persistence**: Final audit results are stored and accessible via existing API endpoints (`get_audit_status`, `get_audit_issues`) or the web dashboard

The entire process runs within the Cloudflare Workers environment, requiring no external infrastructure or keep-alive services.

## Summary

- **OpenSEO** supports automated scheduling through Cloudflare Workers **scheduled events** defined in [[`worker-configuration.d.ts`](https://github.com/every-app/open-seo/blob/main/worker-configuration.d.ts)](https://github.com/every-app/open-seo/blob/main/worker-configuration.d.ts)
- Implement a `scheduled` handler that invokes `AuditService.startAudit()` to programmatically start audits
- Configure execution cadence using standard cron syntax in [`wrangler.toml`](https://github.com/every-app/open-seo/blob/main/wrangler.toml)
- The audit leverages the existing **SiteAuditWorkflow** architecture, reusing the same phases and repository patterns as manual audits
- Monitor automated runs through the existing progress tracking and status endpoints

## Frequently Asked Questions

### Can I schedule audits for multiple websites simultaneously?

Yes. Extend the scheduled handler to iterate over an array of project configurations, calling `AuditService.startAudit()` for each site. Be mindful of Cloudflare Workers' execution time limits when scheduling large batches concurrently.

### How do I monitor the status of scheduled audits?

Scheduled audits use the same progress tracking as manual audits. Query the audit status through the `get_audit_status` endpoint or check the **AuditProgressKV** storage directly. The audit ID returned by `startAudit()` can be logged to your monitoring system for correlation.

### What cron syntax does OpenSEO support?

OpenSEO inherits cron capabilities from Cloudflare Workers, which supports standard UNIX cron syntax with five fields (minute, hour, day of month, month, day of week). You can test expressions in the Cloudflare dashboard before deploying.

### Will scheduled audits impact my Cloudflare Worker request limits?

Scheduled invocations count toward your Worker invocation quotas, but they execute independently of HTTP request traffic. The audit workflow itself may make outbound requests to crawl your site, which count toward subrequest limits, but the scheduling mechanism adds minimal overhead.