cloudflare-cron-triggers について
Cloudflare Workers 開発者向けの Cron Triggers スキルです。スケジュール実行ハンドラーの実装、設定、テスト、デプロイを案内し、Cron 式や連携パターン、トラブルシューティングを扱います。
主な機能
- 01スケジュール実行ハンドラーの実装ガイド
- 025フィールド Cron 式リファレンス
- 03Wrangler のトリガー設定
- 04ローカルテストとデプロイのガイド
- 05複数スケジュールと連携パターン
- 06一般的なエラーのトラブルシューティング
活用シーン
- 01データベースのクリーンアップを定期実行
- 02レポートの定期生成
- 03複数のスケジュールによるタスク振り分け
- 04スケジュール実行ハンドラーのローカル検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill cloudflare-cron-triggersインストール後、Claude Code で/cloudflare-cron-triggersを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/common-patterns.mdcron-expressions-reference.mdintegration-patterns.mdtesting-guide.mdwrangler-config.mdtemplates/basic-scheduled.tshono-with-scheduled.tsmultiple-crons.tsscheduled-with-bindings.tswrangler-cron-config.jsonc詳細
Cloudflare Cron Triggers
ステータス:本番環境で利用可能 ✅ 最終更新日:2025-11-25 依存関係:cloudflare-worker-base(Worker のセットアップ用) 最新バージョン:[email protected]、@cloudflare/[email protected]
クイックスタート(5 分)
1. Worker にスケジュールハンドラーを追加する
src/index.ts:
export default {
async scheduled(
controller: ScheduledController,
env: Env,
ctx: ExecutionContext
): Promise<void> {
console.log('Cron job executed at:', new Date(controller.scheduledTime));
console.log('Triggered by cron:', controller.cron);
// Your scheduled task logic here
await doPeriodicTask(env);
},
};
重要な理由:
- ハンドラーの名前は必ず
scheduledにしてください(scheduledHandlerやonScheduledではありません) - default export オブジェクトでエクスポートする必要があります
- ES モジュール形式を使用する必要があります(Service Worker 形式ではありません)
2. Wrangler で Cron Trigger を設定する
wrangler.jsonc:
{
"name": "my-scheduled-worker",
"main": "src/index.ts",
"compatibility_date": "2025-10-23",
"triggers": {
"crons": [
"0 * * * *" // Every hour at minute 0
]
}
}
重要:
- Cron 式は 5 つのフィールドを使用します:
minute hour day-of-month month day-of-week - すべての時刻は UTC のみ です(タイムゾーン変換はありません)
- 変更が全世界に反映されるまで、最大 15 分かかります
3. ローカルでテストする
# Enable scheduled testing
bunx wrangler dev --test-scheduled
# In another terminal, trigger the scheduled handler
curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*"
# View output in wrangler dev terminal
テストのヒント:
/__scheduledエンドポイントは--test-scheduledフラグを指定した場合にのみ利用できます- クエリパラメーターに任意の Cron 式を渡せます
- Python Workers では、代わりに
/cdn-cgi/handler/scheduledを使用します
4. デプロイする
npm run deploy
# or
bunx wrangler deploy
デプロイ後:
- 変更が反映されるまで、最大 15 分かかることがあります
- ダッシュボードを確認してください:Workers & Pages > [Your Worker] > Cron Triggers
- 過去の実行履歴は Logs タブで確認できます
リファレンスを読み込むタイミング
ユーザーが次の内容に言及したら、すぐに読み込みます:
cron-expressions-reference.md→ 「cron 構文」、「スケジュール形式」、「式」、「分 時 日」、「X 分ごと」common-patterns.md→ 「例」、「ユースケース」、「パターン」、「実例」、「データベースのクリーンアップ」、「レポートの生成」、「方法」integration-patterns.md→ 「実装」、「Hono」、「複数のトリガー」、「バインディング」、「ワークフロー」、「エラー処理」wrangler-config.md→ 「設定」、「wrangler.jsonc」、「複数の cron」、「環境固有」、「開発環境 ステージング 本番環境」testing-guide.md→ 「テスト」、「ローカル開発」、「__scheduled」、「ユニットテスト」、「curl」、「デバッグ」
次の場合は先回りして読み込みます:
- 新しいスケジュールタスクを作成する場合 →
integration-patterns.mdを読み込みます - wrangler.jsonc を設定する場合 →
wrangler-config.mdを読み込みます - Cron 式をデバッグする場合 →
cron-expressions-reference.mdを読み込みます - ローカルでテストする場合 →
testing-guide.mdを読み込みます - 例を探している場合 →
common-patterns.mdを読み込みます
Cron 式の構文
5 フィールド形式
* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of Week (0-6, Sunday=0)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of Month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
特殊文字
| 文字 | 意味 | 例 |
|---|---|---|
* | 毎 | * * * * * = 毎分 |
, | リスト | 0,30 * * * * = 毎時 :00 と :30 |
- | 範囲 | 0 9-17 * * * = 午前 9 時から午後 5 時まで毎時 |
/ | 間隔 | */15 * * * * = 15 分ごと |
よく使われるパターン
# Every minute
* * * * *
# Every 5 minutes
*/5 * * * *
# Every 15 minutes
*/15 * * * *
# Every hour at minute 0
0 * * * *
# Every hour at minute 30
30 * * * *
# Every 6 hours
0 */6 * * *
# Every day at midnight (00:00 UTC)
0 0 * * *
# Every day at noon (12:00 UTC)
0 12 * * *
# Every day at 3:30am UTC
30 3 * * *
# Every Monday at 9am UTC
0 9 * * 1
# Every weekday at 9am UTC
0 9 * * 1-5
# Every Sunday at midnight UTC
0 0 * * 0
# First day of every month at midnight UTC
0 0 1 * *
# Twice a day (6am and 6pm UTC)
0 6,18 * * *
# Every 30 minutes during business hours (9am-5pm UTC, weekdays)
*/30 9-17 * * 1-5
重要:タイムゾーンは UTC のみ
- すべての Cron Trigger は UTC 時刻で実行されます
- タイムゾーン変換は利用できません
- 現地時刻を手動で UTC に変換してください
- 例:PST の午前 9 時 = UTC の午後 5 時(DST 期間中は翌日)
ScheduledController インターフェース
interface ScheduledController {
readonly cron: string; // The cron expression that triggered this execution
readonly type: string; // Always "scheduled"
readonly scheduledTime: number; // Unix timestamp (ms) when scheduled
}
プロパティ
controller.cron(string)
この実行をトリガーした Cron 式です。
export default {
async scheduled(controller: ScheduledController, env: Env): Promise<void> {
console.log(`Triggered by: ${controller.cron}`);
// Output: "Triggered by: 0 * * * *"
},
};
**用途:**複数の Cron スケジュールを区別します(複数の Cron Trigger パターンを参照)。
controller.type(string)
Cron によってトリガーされた実行では、常に "scheduled" を返します。
if (controller.type === 'scheduled') {
// This is a cron-triggered execution
}
controller.scheduledTime(number)
この実行が予定されていた時刻の Unix タイムスタンプ(エポックからの経過時間、ミリ秒)です。
export default {
async scheduled(controller: ScheduledController): Promise<void> {
const scheduledDate = new Date(controller.scheduledTime);
console.log(`Scheduled for: ${scheduledDate.toISOString()}`);
// Output: "Scheduled for: 2025-10-23T15:00:00.000Z"
},
};
**注:**これは実際の実行時刻ではなく、予定時刻です。システム負荷により、実際の実行はわずかに遅れることがあります(通常は 1 秒未満)。
実行コンテキスト
export default {
async scheduled(
controller: ScheduledController,
env: Env,
ctx: ExecutionContext // ← Execution context
): Promise<void> {
// Use ctx.waitUntil() for async operations that should complete
ctx.waitUntil(logToAnalytics(env));
},
};
ctx.waitUntil(promise: Promise<any>)
ハンドラーの戻り後も非同期処理が完了するまで待機するよう、実行コンテキストを拡張します。
用途:
- 外部サービスへのログ記録
- アナリティクスのトラッキング
- クリーンアップ処理
- 重要度の低いバックグラウンドタスク
export default {
async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext): Promise<void> {
// Critical task - must complete before handler exits
await processData(env);
// Non-critical tasks - can complete in background
ctx.waitUntil(sendMetrics(env));
ctx.waitUntil(cleanupOldData(env));
ctx.waitUntil(notifySlack({ message: 'Cron completed' }));
},
};
**重要:**失敗した最初の waitUntil() が、ダッシュボードのログにステータスとして報告されます。
統合パターン
本番環境ですぐに使える6つのCronパターン:
- Cronを使用したスタンドアロンワーカー - バックグラウンドタスク(データベースのクリーンアップ、レポートの生成)用の単一のスケジュール関数
- HonoとCronの組み合わせ - 1つのWorkerでHTTPエンドポイントとスケジュールタスクを実行し、バインディングを共有してコストを削減します
- 複数のCronトリガー -
controller.cronを使って実行を振り分け、タスクごとに異なるスケジュールを設定します - バインディングへのアクセス - スケジュール関数でD1、KV、R2、AI、Vectorize、Queues、Workflows、Durable Objectsを使用します
- Workflowsとの統合 - 複雑で長時間にわたる複数ステップのワークフローをスケジュールに従ってトリガーします
- エラーハンドリングのベストプラクティス - 再試行ロジック、アラート(Slack/メール)、失敗ログの記録、モニタリングを備えた包括的なエラーハンドリングを行います
完全な実装例、コードサンプル、設定の詳細、ベストプラクティスについては、references/integration-patterns.md を読み込んでください。
Wranglerの設定
triggers.crons 配列にCronトリガーを追加します。各トリガーには cron 式が必要です。複数のCron(Freeプランでは最大3つ、有料プランでは上限が高くなります)と、dev/staging/productionのデプロイ向けの環境別設定に対応しています。
複数のトリガー、環境別のスケジュール、タイムゾーンの処理、削除手順を含む完全な設定例については、references/wrangler-config.md を読み込んでください。
テストと開発
bunx wrangler dev --test-scheduled を実行して /__scheduled エンドポイントを使い、スケジュール関数をローカルでテストします。その後、curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*" を実行してハンドラーをトリガーします(Cron式ではスペースの代わりに + を使用してください)。
完全なテスト戦略、ローカル開発環境のセットアップ、単体テストの例、統合テストのパターン、本番環境のモニタリング手法については、references/testing-guide.md を読み込んでください。
Green Compute
再生可能エネルギーで稼働するデータセンターでのみCronトリガーを実行します。
Green Computeを有効にする
ダッシュボードから:
- Workers & Pagesに移動します
- Account details セクションで、Compute Setting を見つけます
- Change をクリックします
- Green Compute を選択します
- Confirm をクリックします
適用対象:
- アカウント内のすべてのCronトリガー
- 炭素排出量を削減します
- 追加料金はかかりません
- 一部のリージョンでは若干の遅延が生じる場合があります
仕組み:
- CloudflareがCronの実行を再生可能エネルギーで稼働するデータセンターにルーティングします
- 風力、太陽光、水力発電などの再生可能エネルギーを使用します
- 電力購入契約(PPA)と再生可能エネルギー証書(REC)を通じて検証されます
既知の問題の防止
このスキルは、文書化されている6件の問題を防ぎます。
問題#1:Cronの変更が反映されない
エラー: wrangler.jsoncでCronトリガーを更新しても実行されない
ソース: Cloudflare Docs - Cron Triggers
発生する理由:
- Cronトリガーの変更がグローバルに反映されるまで、最大15分かかります
- Cloudflareネットワークがエッジノードを更新するには時間が必要です
- 通常のデプロイのように即時には反映されません
防止策:
- デプロイ後、実行を確認するまで15分待ちます
- ダッシュボードで確認します:Workers & Pages > [Worker] > Cron Triggers
- トリガーのみを変更する場合は
wrangler triggers deployを使用します
# If you only changed triggers (not code), use:
bunx wrangler triggers deploy
# Wait 15 minutes, then verify in dashboard
問題#2:ハンドラーがエクスポートされていない
エラー: Handler does not export a 'scheduled' method
ソース: よくあるデプロイエラー
発生する理由:
- ハンドラーの名前が正確に
scheduledになっていません - ハンドラーがデフォルトのエクスポートオブジェクトでエクスポートされていません
- ESモジュール形式ではなくService Worker形式を使用しています
防止策:
// ❌ Wrong: Incorrect handler name
export default {
async scheduledHandler(controller, env, ctx) { }
};
// ❌ Wrong: Not in default export
export async function scheduled(controller, env, ctx) { }
// ✅ Correct: Named 'scheduled' in default export
export default {
async scheduled(controller, env, ctx) { }
};
Issue #3:UTC タイムゾーンの混乱
エラー: Cron が間違った時刻に実行される
原因: ユーザーの想定と実際の動作の違い
発生する理由:
- すべての cron トリガーは UTC 時刻のみで実行されます
- タイムゾーンの変換には対応していません
- ユーザーはローカルタイムゾーンでの実行を想定しています
防止策:
ローカル時刻を手動で UTC に変換してください:
// Want to run at 9am PST (UTC-8)?
// 9am PST = 5pm UTC (17:00)
{
"triggers": {
"crons": ["0 17 * * *"] // 9am PST = 5pm UTC
}
}
// Want to run at 6pm EST (UTC-5)?
// 6pm EST = 11pm UTC (23:00)
{
"triggers": {
"crons": ["0 23 * * *"] // 6pm EST = 11pm UTC
}
}
// Remember: DST changes affect conversion!
// PST is UTC-8, PDT is UTC-7
ツール:
Issue #4:無効な Cron 式
エラー: Cron が実行されず、エラーも表示されない
原因: 検証が通知されずに失敗する
発生する理由:
- 無効な cron 構文は、通知されずに失敗します
- 検証はデプロイ時に行われますが、気づきにくい場合があります
- よくある間違い:フィールドの順序が誤っている、無効な範囲を指定している
防止策:
# ❌ Wrong: Too many fields (6 fields instead of 5)
"crons": ["0 0 * * * *"] # Has seconds field - not supported
# ❌ Wrong: Invalid minute range
"crons": ["65 * * * *"] # Minute must be 0-59
# ❌ Wrong: Invalid day of week
"crons": ["0 0 * * 7"] # Day of week is 0-6 (use 0 for Sunday)
# ✅ Correct: 5 fields, valid ranges
"crons": ["0 0 * * 0"] # Sunday at midnight UTC
検証方法:
- Crontab Guru で式を検証します
- wrangler deploy の出力にエラーがないか確認します
--test-scheduledを使ってローカルでテストします
Issue #5:ES モジュール形式が不足している
エラー: Worker must use ES modules format
原因: レガシーな Service Worker 形式
発生する理由:
- スケジュールされたハンドラーには ES モジュール形式が必要です
- 古い Service Worker 形式には対応していません
- コードベース内で形式が混在しています
防止策:
// ❌ Wrong: Service Worker format
addEventListener('scheduled', (event) => {
event.waitUntil(handleScheduled(event));
});
// ✅ Correct: ES modules format
export default {
async scheduled(controller, env, ctx) {
await handleScheduled(controller, env, ctx);
},
};
Issue #6:CPU 時間制限を超過した
エラー: CPU time limit exceeded
原因: 実行時間の長いスケジュールタスク
発生する理由:
- デフォルトの CPU 制限は 30 秒です
- 実行時間の長いタスクは制限を超過します
- タイムアウトは自動延長されません
防止策:
オプション 1:wrangler.jsonc で CPU 制限を引き上げる
{
"limits": {
"cpu_ms": 300000 // 5 minutes (max for Standard plan)
}
}
オプション 2:実行時間の長いタスクには Workflows を使用する
// Instead of long task in cron:
export default {
async scheduled(controller, env, ctx) {
// Trigger Workflow that can run for hours
await env.MY_WORKFLOW.create({
params: { task: 'long-running-job' },
});
},
};
オプション 3:小さなチャンクに分割する
export default {
async scheduled(controller, env, ctx) {
// Process in batches
const batch = await getNextBatch(env.DB);
for (const item of batch) {
await processItem(item);
}
// If more work, send to Queue for next batch
const hasMore = await hasMoreWork(env.DB);
if (hasMore) {
await env.MY_QUEUE.send({ type: 'continue-processing' });
}
},
};
必ず行うこと ✅
- 正確なハンドラー名を使う -
scheduledHandlerやその派生名ではなく、scheduledを使う必要があります - ES モジュール形式を使う - addEventListener ではなく、デフォルトオブジェクトでエクスポートします
- UTC に変換する - すべての cron 時刻は UTC です。ローカルタイムゾーンから変換してください
- 15 分待つ - cron の変更が反映されるまで、最大 15 分かかります
- まずローカルでテストする -
wrangler dev --test-scheduledを使います - cron 構文を検証する - Crontab Guru を使います
- エラーを適切に処理する - ログを記録し、アラートを出し、必要に応じて再スローします
- ctx.waitUntil() を使う - 重要でない非同期処理に使います
- Workflows を検討する - 30 秒を超える CPU 時間が必要なタスクに使います
- 実行を監視する - ダッシュボードのログを定期的に確認します
絶対に行わないこと ❌
- ローカルタイムゾーンを前提にしない - すべての cron は UTC で実行されます
- 6 フィールドの cron 式を使わない - Cloudflare は 5 フィールド形式を使用します(秒は含みません)
- 変更が即座に反映されると期待しない - 反映には最大 15 分かかります
- Service Worker 形式を使わない - ES モジュール形式を使う必要があります
- エラー処理を忘れない - 捕捉されないエラーは通知されずに失敗します
- 制限を引き上げずに CPU 負荷の高いタスクを実行しない - デフォルトの制限は 30 秒です
- 曜日に 7 を使わない - 日曜日には 0 を使います(範囲は 0~6 のみ)
- テストせずにデプロイしない - まず必ず
--test-scheduledでテストします - 実行ログを無視しない - ダッシュボードで過去の失敗を確認できます
- テスト用のスケジュールをハードコードしない - 環境ごとの設定を使います
よくあるユースケース
references/common-patterns.md を読み込み、データベースのクリーンアップ、API データの収集、日次レポートの生成、キャッシュのウォームアップ、監視とヘルスチェック、データ同期、バックアップの自動化、サイトマップの生成、Webhook の処理、スケジュール通知など、実際に使われている 10 種類の cron パターンを確認してください。
TypeScript 型
// Scheduled event controller
interface ScheduledController {
readonly cron: string;
readonly type: string;
readonly scheduledTime: number;
}
// Execution context
interface ExecutionContext {
waitUntil(promise: Promise<any>): void;
passThroughOnException(): void;
}
// Scheduled handler
export default {
async scheduled(
controller: ScheduledController,
env: Env,
ctx: ExecutionContext
): Promise<void>;
}
制限と料金
制限
| 機能 | 無料プラン | 有料プラン |
|---|---|---|
| Worker ごとの Cron トリガー数 | 3 | それ以上(ドキュメントを確認してください) |
| 1 回の実行あたりの CPU 時間 | 10 ms(平均) | 30 秒(デフォルト)、5 分(最大) |
| 実時間 | 30 秒 | 15 分 |
| メモリ | 128 MB | 128 MB |
料金
Cron トリガーには Standard Workers の料金が適用されます。
- Workers Paid Plan:月額 $5 が必要です
- リクエスト:100 万リクエストあたり $0.30(無料枠の 1,000 万件を超えた後)
- CPU 時間:100 万 CPU-ms あたり $0.02(無料枠の 3,000 万件を超えた後)
Cron の実行 = 1 リクエスト
例:
- Cron を毎時実行(1 日 24 回)
- 30 日 × 24 回の実行 = 月 720 回の実行
- 1 回の実行あたり平均 50ms の CPU 時間
費用:
- リクエスト:720 件(無料枠の 1,000 万件を大きく下回ります)
- CPU 時間:720 × 50ms = 36,000ms(無料枠の 3,000 万件を下回ります)
- 合計:月額 $5(サブスクリプション料金のみ)
高頻度の例:
- Cron を毎分実行(1 日 1440 回)
- 30 日 × 1440 回 = 月 43,200 回の実行
- それでも無料枠の上限を下回ります
- 合計:月額 $5
トラブルシューティング
問題:Cron が実行されない
考えられる原因:
- 変更がまだ反映されていない(15 分待ちます)
- Cron 式が無効です
- ハンドラーが正しくエクスポートされていません
- Worker がデプロイされていません
解決方法:
# Re-deploy
bunx wrangler deploy
# Wait 15 minutes
# Check dashboard
# Workers & Pages > [Worker] > Cron Triggers
# Check logs
# Workers & Pages > [Worker] > Logs > Real-time Logs
問題:ハンドラーは実行されるが失敗する
考えられる原因:
- ハンドラー内でエラーが捕捉されていません
- CPU 時間の上限を超えています
- 環境バインディングが不足しています
- ネットワークがタイムアウトしています
解決方法:
export default {
async scheduled(controller, env, ctx) {
try {
await yourTask(env);
} catch (error) {
// Log detailed error
console.error('Handler failed:', {
error: error.message,
stack: error.stack,
cron: controller.cron,
time: new Date(controller.scheduledTime),
});
// Send alert
ctx.waitUntil(sendAlert(error));
// Re-throw to mark as failed
throw error;
}
},
};
エラーの詳細はダッシュボードのログを確認してください。
問題:実行時刻が正しくない
原因: UTC と現地時間の混同
解決方法:
希望する現地時間を UTC に変換します。
// Want 9am PST (UTC-8)?
// 9am PST = 5pm UTC (17:00)
{
"triggers": {
"crons": ["0 17 * * *"]
}
}
ツール:
- 世界時計コンバーター
- DST の変更(PST と PDT)に注意してください
問題:ローカルテストが機能しない
考えられる原因:
--test-scheduledフラグがありません- エンドポイントが間違っています(
/__scheduledである必要があります) - Python Worker の場合(
/cdn-cgi/handler/scheduledを使用します)
解決方法:
# Correct: Start with flag
bunx wrangler dev --test-scheduled
# In another terminal
curl "http://localhost:8787/__scheduled?cron=0+*+*+*+*"
本番環境へのデプロイ前チェックリスト
Cron トリガーを本番環境にデプロイする前に、以下を確認してください。
- Crontab Guru で Cron 式を検証済み
- デフォルトエクスポート内のハンドラー名が正確に
scheduled - ES モジュール形式を使用(Service Worker 形式ではない)
- 現地時間を UTC に変換済み
- ログ記録を含むエラー処理を実装済み
- 失敗時のアラートを設定済み
- 必要に応じて CPU 上限を引き上げ済み(
limits.cpu_ms) - 環境バインディングをテスト済み
-
--test-scheduledを使ってローカルでテスト済み - ステージング環境でデプロイをテスト済み
- デプロイ後、反映のために 15 分待機済み
- ダッシュボードのログで実行を確認済み
- モニタリングとアラートを設定済み
- スケジュールの詳細をドキュメントに反映済み
関連ドキュメント
- Cloudflare Cron Triggers:https://developers.cloudflare.com/workers/configuration/cron-triggers/
- Scheduled Handler API:https://developers.cloudflare.com/workers/runtime-apis/handlers/scheduled/
- Cron Trigger Examples:https://developers.cloudflare.com/workers/examples/cron-trigger/
- Multiple Cron Triggers:https://developers.cloudflare.com/workers/examples/multiple-cron-triggers/
- Wrangler Triggers Command:https://developers.cloudflare.com/workers/wrangler/commands/#triggers
- Workers Pricing:https://developers.cloudflare.com/workers/platform/pricing/
- Workflows Integration:https://developers.cloudflare.com/workflows/
- Crontab Guru(バリデーター):https://crontab.guru/
- タイムゾーンコンバーター:https://www.timeanddate.com/worldclock/converter.html
最終更新日:2025-10-23 バージョン:1.0.0 メンテナー:Claude Skills Maintainers | [email protected]