GASの6分タイムアウト制限突破|Cloud Run Functionsでスプシ自動更新
Google Apps Script(GAS)はスプレッドシート自動化に非常に便利ですが、実行時間が最大6分という制限があります。
今回、APIを呼び出してデータを取得し、スプレッドシートへ転記する処理を毎日実行していました。しかしAPI応答が遅く、合計で6分以上かかる状態になり、処理が不安定に。タイムアウト寸前、もしくは失敗することが発生していました。
そこで、重い処理をCloud Run Functionsへ移行し、安定化させました。
この記事ではその具体的なGASからCloud Run Functionsへの移行の方法を紹介します!
目次
今回の要件と課題
要件は以下です。
-
APIを呼び出し
-
取得データをスプレッドシートへ転記
-
毎日自動実行
-
既存のGASコード資産を可能な限り活用したい
課題は
-
API応答に時間がかかる
-
GASの6分制限がボトルネック
アーキテクチャ構成

GASは完全に排除するのではなく、必要に応じて手動トリガー用として残せる設計にしています。
ポイントは:
-
毎日実行はCloud Scheduler
-
重い処理はCloud Run
-
スプレッドシート更新もCloud Run側で完結
これにより、GASの実行制限から完全に解放されました。
IAMサービスアカウントの設計
Cloud Runからスプレッドシートを更新するために、専用のサービスアカウントを発行しました。
手順概要
-
IAM & 管理 → サービスアカウント作成

-
以下のロールを付与
-
Cloud Run Invoker(必要に応じて)
-
Logs Writer
-
Editor(またはSheets API限定ロール)
-
-
Sheets APIを有効化


-
対象スプレッドシートにサービスアカウントのメールアドレスを共有

Cloud Run Functionsのコンテナ設定
今回はCloud Run Functions(第2世代)を使用しました。

主な設定
-
ランタイム:Node.js 20
-
メモリ:512MB
-
タイムアウト:最大60分(実際は10分程度)
-
同時実行数:デフォルト
API呼び出しは並列化しています。
またコード内で使用するため、自動化したいスプシのIDをSPREADSHEET_IDとして環境変数に登録しておきます。

ディレクトリ設定
Cloud Run Functions側のコードは、できるだけ責務を分離したシンプルな構成にしています。
/src
├ index.js // エントリポイント
├ gasShim.js // GAS互換レイヤー
└ main.js // スプレッドシート更新処理
エントリポイント:index.js
Cloud Run FunctionsではHTTPハンドラを定義します。
今回はCloud Schedulerから呼び出すだけなので、非常にシンプルです。
import { runBatch } from "./batch.js";
export const main = async (req, res) => {
try {
await runBatch();
res.status(200).send("success");
} catch (err) {
console.error(err);
res.status(500).send("error");
}
};
GASコード資産を活かす:gasShim.js
今回の工夫ポイントはここです。
既存のGASコードをなるべくそのまま使いたかったため、gasShim.jsを作成しました。
GAS特有のオブジェクト(例:UrlFetchApp, PropertiesServiceなど)をNode.js環境で疑似的に再現するラッパーです。
例えば、GASでは次のようにスプレッドシートを操作します。
const sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
このAPIをNode.jsでも使えるように、SpreadsheetAppをラップしたクラスを用意します。
const { google } = require('googleapis');
class SpreadsheetAppShim {
constructor(spreadsheetId, auth) {
this.spreadsheetId = spreadsheetId;
this.sheetsApi = google.sheets({ version: 'v4', auth });
}
getActiveSpreadsheet() {
return this;
}
async getSheets() {
const res = await this.sheetsApi.spreadsheets.get({
spreadsheetId: this.spreadsheetId
});
return res.data.sheets.map(
s => new SheetShim(this.spreadsheetId, s.properties.title, this.sheetsApi)
);
}
}
内部ではGoogle Sheets APIを呼び出していますが、外側から見るとGASのAPIとほぼ同じインターフェースになります。
これにより、
-
GASで書いた既存コードをほぼそのまま移植可能
-
Cloud Run上で実行可能
-
ローカル開発もしやすい
というメリットがあります。
この設定をした場合、GASでこのように書く場合
const values = sheet.getRange(1,1,10,3).getValues();
Cloud Run Functionsのmain.jsでは以下のように再現できます。
const values = await sheet.getRange(1,1,10,3).getValues();

スプレッドシート更新:main.js
これまで使用していたGASのコードを、上記のgasShim.jsに合わせて少し修正します。

Cloud Schedulerで定期実行設定
GASでトリガーを作成するように、Cloud SchedulerでCloud Run Functionsのエンドポイントを定期実行します。
Cloud Schedulerでジョブの作成から名前/cronでの頻度設定を記載します。
実行内容の構成の部分では「HTTP」、URLにはCloud Run Functionsで作成したURLを記載します。

これにより、GASのトリガーを使わずに安定した定期バッチ処理を実行できます。
まとめ
この記事が参考になった方は「いいね」やシェアをお願いします!
編集者
エンジニアチーム
編集者
エンジニアチーム
GASやLooker Studio、TROCCOなどのツールを活用した、業務効率化やデータ活用のノウハウをわかりやすく発信しています!