Experiment record

Apps Script時間主導トリガーでのみ発生したOpen-Meteo HTTP 429

同じGoogle Apps Script収集関数が手動実行ではHTTP 200、時間主導トリガーではHTTP 429となった。保持証拠からは、収集コードそのものより時間主導トリガー側で使われるGoogleの外向きネットワーク経路が関係した可能性が高い。Googleの共有送信元側で他のApps Script通信と利用量が合算された可能性は仮説であり、Cloudflare Worker経由への変更後には調査対象の収集が復旧した。

概要

Google Apps ScriptからOpen-Meteoへデータ取得リクエストを送る収集関数で、同じ関数を手動実行するとHTTP 200で成功する一方、時間主導トリガーから実行するとHTTP 429になる現象を確認しました。

調査では、手動実行と時間主導トリガー実行の違いを切り分けるため、実行コンテキストの診断、外向きネットワーク経路の一時確認、収集コードの確認、Cloudflare Workerリレーを使った回避を順に行いました。

保持証拠を総合すると、今回の429は収集コード内の通常リクエストロジックの違いよりも、時間主導トリガーからOpen-Meteoへアクセスするときに使われるGoogle側の外向きネットワーク経路に関係した可能性が高いと考えられます。

Googleの公式ドキュメントでは、Apps ScriptのUrlFetchAppはGoogleのネットワーク基盤を使用し、リクエストはGoogleのIPレンジのプールから送信されると説明されています。この情報は、共有の送信元ネットワークがOpen-Meteoの利用上限判定に影響した可能性と整合します。

ただし、Open-Meteoが実際に他のApps Script利用者や別ワークロードの通信まで同じ利用量として合算していたことは確認できていません。 この具体的な集計メカニズムは仮説です。

Open-MeteoへのリクエストをCloudflare Workerリレー経由へ変更した後、調査対象のスケジュール収集が復旧したとの保持記録があります。一方、これはOpen-Meteoのレート制限そのものが解除されたことを意味せず、経路を変えた回避策として解釈する必要があります。

実験の背景

Open-MeteoへアクセスするGoogle Apps Script収集関数を運用していたところ、手動実行と時間主導トリガー実行で結果が分かれました。

手動実行ではHTTP 200で成功するのに対し、同一関数を時間主導トリガーから実行すると、daily API request limitメッセージを伴うHTTP 429が返りました。

この差が、トリガー時だけ発生する追加リクエストや異なるアプリケーションコードパスによるものなのか、それとも外向きネットワーク経路の違いに関係するのかを切り分ける必要がありました。また、プロバイダー側の未公開なレート制限キーを推測で確定事項にしないことも重要でした。

実験方法

実験対象

比較対象は同一のGoogle Apps Script収集関数と、その関数からアクセスするOpen-Meteo APIです。

同じ収集関数を手動で実行した場合と、時間主導トリガーから実行した場合のHTTP結果を比較しました。

実験環境

主な実験環境は次のとおりです。

収集設計では、タイムスタンプベースの重複排除と72時間に限定した履歴取得範囲を維持していました。

比較・診断方法

手動実行と時間主導トリガー実行について、HTTPステータス、トリガーイベントによる実行コンテキスト、外向きネットワーク経路を比較しました。さらに、収集コードを確認し、トリガー実行時だけOpen-Meteoへの追加リクエストが生じていないか、HTTP 429時に反復呼び出しが続いていないかを確認しました。

経路変更の効果を確認するため、Open-MeteoへのアクセスをCloudflare Workerリレー経由へ変更しました。

公式仕様との照合

2026年8月23日の解釈見直しでは、保持された観測とGoogle・Open-Meteoの公式資料を照合しました。

GoogleはUrlFetchAppの公式リファレンスで、URL FetchサービスがGoogleのネットワーク基盤を使用し、リクエストがGoogleのIPレンジのプールから送信されることを説明しています。したがって、Apps Scriptからの外部アクセスを各スクリプト専用の固有送信元とみなすことはできません。

Open-MeteoのPricingではFree APIに日次を含む利用上限が示され、Termsでは技術的理由や不正利用防止のためIPアドレスを扱う可能性や、applicationsおよびIP addressesをブロックする場合があることが説明されています。

これらの公式情報は送信元ネットワークがレート制限に関係する可能性とは整合しますが、今回の429でOpen-Meteoが具体的にどのIP、ネットワーク識別子、アプリケーション単位、またはその組み合わせを利用量の集計キーにしたかは確定できません。

実験ログ

保持されている元記録には各操作の正確な実行時刻が残っていないため、以下は記録されている調査順序です。

手動実行と時間主導トリガー実行を比較

同一の収集関数を手動実行すると、Open-MeteoからHTTP 200が返りました。

一方、時間主導トリガーから同じ関数を実行すると、daily API request limitメッセージを伴うHTTP 429が返りました。

同じ収集関数で実行方法によって結果が分かれたため、通常のリクエストURLや関数ロジックだけでは説明できない可能性が生じました。

診断ログで実行コンテキストを確認

診断ログでは、トリガーイベントオブジェクトを使って、手動実行をMANUAL、時間主導トリガー実行をTRIGGERとして識別できました。

これにより、同じ収集関数の中で実行コンテキストを区別しながら結果を比較できました。

外向きネットワーク経路を一時確認

一時的な外部IP確認では、手動実行と時間主導トリガー実行で外向き経路に違いが観測されました。

手動実行ではIPv6が観測され、時間主導トリガー実行ではそれとは異なるIPv4が観測されました。

正確なIPアドレスは公開していません。また、この確認先はOpen-Meteoそのものではないため、この観測だけでは外部IP確認先とOpen-Meteoが常に同じ送信元識別子を観測していたとは確定できません。

収集コードを確認

収集コードを確認したところ、時間主導トリガー実行時だけOpen-Meteoへの追加リクエストが発生する処理は見つかりませんでした。

また、HTTP 429が返った場合、リトライループはプロバイダーへの反復呼び出しを続けず停止していました。

確認したコード範囲では、トリガー時だけ余分なOpen-Meteoリクエストが増えて429を引き起こしたという説明は支持されませんでした。

Cloudflare Workerリレーへ変更

Open-Meteoへのリクエスト経路をCloudflare Workerリレー経由へ変更しました。

保持記録には、この変更後に調査対象の時間主導トリガーによる収集が復旧したことが記録されています。

タイムスタンプベースの重複排除と72時間に限定した履歴取得範囲は維持されました。

結論

時間主導トリガー側の外向き経路が関係した可能性

手動実行ではHTTP 200、時間主導トリガー実行ではHTTP 429となり、確認したコードにはトリガー時だけ増えるOpen-Meteoリクエストが見つかりませんでした。加えて、一時確認では両実行方法で異なる外向きネットワーク経路が観測されました。

これらのEvidenceから、今回の429は収集関数内の通常リクエストロジックの違いよりも、時間主導トリガーから外部へ出る際のGoogle側ネットワーク経路に関係した可能性が高いと推論できます。

GoogleがUrlFetchAppについてGoogleのネットワーク基盤とIPレンジプールを使用すると説明していることも、この解釈と整合します。

共有送信元で利用量が合算された可能性は未検証

時間主導トリガーで使われたGoogle側の送信元ネットワーク識別子またはIPプールを、Open-Meteoが利用量の集計単位として扱っていた可能性があります。その場合、同じ送信元として見える他のApps Scriptワークロードの通信も利用量に寄与した可能性があります。

ただし、この実験では他のApps Script利用者の通信量やOpen-Meteo内部のquota bucketを観測していません。そのため、他のApps Script通信と実際に合算されたという説明はHYPOTHESISであり、確定した結論ではありません。

Cloudflare Workerは経路変更による回避策

Cloudflare Workerリレー経由への変更後にスケジュール収集が復旧したとの保持記録は、経路変更が今回の事例で運用上有効だったことと整合します。

一方、Cloudflare Workerを通すことでOpen-Meteoの利用上限そのものがなくなったことや、Cloudflare経由の通信に恒久的に独立したquotaが与えられることは示されていません。

証拠区分のまとめ

このExperimentで得られた情報のEvidence Stateは次のとおりです。

記録内容Evidence State
今回の429が、収集関数の通常ロジックよりGoogle側の時間主導トリガー用外向き経路に関係した可能性が高いという解釈INFERRED
Open-Meteoが共有Google送信元の利用量を集約し、他のApps Script通信も同じ利用量へ寄与した可能性HYPOTHESIS
Cloudflare Workerリレーへの経路変更後に調査対象のスケジュール収集が復旧したとの保持記録OBSERVED
Cloudflare経由の総利用量が増えた場合に同様のレート制限が再発する可能性HYPOTHESIS
確認したコードにおけるトリガー時だけの追加Open-Meteoリクエストが429の原因だったという説明DISPROVEN

各Evidence Stateの意味はEvidence State(証拠状態)を参照してください。

未解決事項

保持Evidenceからは、次の点を確定できません。

これらを確定するには、Open-Meteo側の利用量集計仕様を確認するか、同等条件で送信元経路と429発生条件を直接観測できる追加Evidenceが必要です。

運用上の示唆

定期収集系では、同じアプリケーション関数を使っていても実行方法によって外部APIの応答が異なる可能性があります。そのため障害診断では、コードとリクエスト内容だけでなく、実行方法、HTTPステータス、トリガーコンテキスト、外向きネットワーク経路を分けて記録する必要があります。

中継経路への変更で復旧した場合も、それだけでプロバイダー側の制限が解除されたとは判断できません。経路変更が有効だった事実と、回避経路側で将来同じ制限が発生し得るかという未解決事項を分離して扱う必要があります。

ネットワーク経路を診断に使う場合は、正確なIPアドレスなどの不要な機微情報を公開せず、問題の切り分けに必要な差分だけを保持・提示する構成が適しています。

実験データについて

元実験の正確な実行時刻と、回避後のスケジュール実行を示す完全なログは、現在確認できる記録には残っていません。

そのため、当時の全実行を時系列で再構成したり、回避後の成功率を後から定量評価したりすることはできません。

当時使用したCloudflare Workerの完全なソースコードも、再現用ソースコードとしては保持されていません。

再現に必要なもの

今回の調査構成を理解・再現するために必要な主な要素は、Google Apps Script、時間主導トリガー、Open-Meteo API、および外向き経路を変更できるリレー環境です。今回のExperimentではCloudflare Workerをそのリレーとして使用しました。

手動実行と時間主導トリガー実行について、HTTPステータス、実行コンテキスト、必要に応じて外向き経路の差を記録できる診断環境も必要です。

元の完全な収集コードとCloudflare Workerコードは保持されていないため、このExperiment Logだけから当時の実装をそのまま再構築することはできません。

本実験では購入が必要な専用機材は使用していません。

機械可読な実験記録

このExperimentの機械可読な正本記録をJSONとして公開しています。

AIEL-2026-0002 experiment.json