コンテンツにスキップ

ファンクションの性質と制約

このページではCraft Functionsの実行環境の性質と制約について説明します。

Craft Functions の性質

Craft Functionsでプログラムを作成する際に考慮すべき性質について説明します。なお、ファンクションの種類によって特有の性質・ルールについては以下をご確認ください。

Craft Functions は実行環境を使い回すことがある

Craft Functionsは実行環境を使い回すことがあります。同一環境上で実行する場合、Craft Functionsは関数外で定義した値を再計算せず、前回実行時と同じ値を使います。したがって、関数定義の外側で処理時間のかかる処理を行うことで、ファンクションを複数実行した際の平均処理時間を短縮できます。

一方で、実行ごとに異なる値を使う必要がある場合はキャッシュによって意図しない動作を引き起こすので注意してください。次のコードは uuid にランダムなUUIDを設定していますが、同一実行環境では上記の挙動により同じ値を返却してしまいます。

import crypto from "crypto";
// 関数の外で uuid を定義
const uuid = crypto.randomUUID();
export default function (data, { MODULES }) {
// 同一実行環境でuuidはキャッシュされるため、短時間に複数回実行すると同じ値が返ることがある
return uuid;
}

コールドスタートが発生することがある

一定期間リクエストがない場合や、同時実行数の増加などにより新しい実行環境(インスタンス)を起動する必要がある場合、コールドスタートが発生します。コールドスタートとは、インスタンスの起動からファンクションのコードが実行可能になるまでにかかる時間のことです。

コールドスタート発生時は、リクエスト受信からファンクションコードの実行開始までに起動時間がかかります。

タイムアウトの計測はリクエストの受信から始まり、この起動時間もタイムアウト時間に含まれます。

その結果、ファンクションコードの処理に使える残り時間は短くなる場合があります。

コールドスタートはインフラ側の通常の挙動であり、発生タイミングや所要時間はリクエストの頻度や負荷状況などに依存するため、事前に予測できません。ウォームな実行環境があるときだけ成り立つ設計は避け、コールドスタートが発生しても業務上問題にならないよう実装してください。

呼び出し方によって、コールドスタートの影響の出方は異なります。

  • HTTPタイプエンドポイントトリガーでは、呼び出し元はレスポンス完了まで待機します。コールドスタートに伴う遅延やタイムアウト(504や502)を受け取る可能性があります
  • イベント駆動タイプでは、トリガー側の再送などと組み合わさると、実行遅延や重複が発生しうる

設計時は、次の点を確認してください。

  • コールドスタートで起動時間が加わっても、タイムアウト(504/502)を超えずに処理を完了できるか
  • 同一の処理が複数回実行されても問題ないか。呼び出し元のタイムアウト・リトライ、またはイベント駆動タイプの再配送(at least once)により、同じリクエストやイベント相当の処理が重複実行されうる
  • レスポンスの遅延を許容できない場合は、Craft Schedulerなどで定期的にファンクションを実行し、実行環境をウォーム状態に保つ

Craft Functions は非同期処理を自動的に完了しない

非同期な処理を行う際は、 必ず関数内で非同期処理の完了を待ってください。 待機しない場合、Craft Functions実行時に次のような不具合が発生し得ます。

  • ファンクションの実行が完了しない、もしくは完了するまでに著しく時間がかかる
  • 次回の実行時に未完了の処理を再開するなど、意図しない挙動となる
  • エラー発生時にログが記録されない

例えば次のようにPromiseチェーンで非同期処理を実装した場合、ファンクションはPromiseチェーン内の非同期処理の完了を待たずに終了することがあります。加えて、次回の実行時に未完了の処理を再開して意図しない挙動をすることがあります。

NGな例
export default function (data, { MODULES }) {
const { initLogger } = MODULES;
const logger = initLogger({ logLevel: "DEBUG" });
// Craft Functionsでは次のfetch APIの呼び出し方は非推奨
// (data) => logger.log(data) が完了するまで待機しなければならない
fetch("http://example.com/movies.json")
.then((response) => response.json())
.then((data) => logger.log(data));
}

この場合、Promiseチェーンで書かれた処理を await で待機することで同期的な処理にできます。

OKな例:Promiseチェーンをawaitする
export default function (data, { MODULES }) {
const { initLogger } = MODULES;
const logger = initLogger({ logLevel: 'DEBUG' });
// await で処理の完了を待つ
await fetch("http://example.com/movies.json")
.then((response) => response.json())
.then((data) => logger.log(data));
}

また、一般的にPromiseチェーンはasync/awaitを使った処理に書き換えられます。非同期処理を実装する際は、await式を適切に利用してください。

OKな例:aync/await を使って書き換える
export default function (data, { MODULES }) {
const { initLogger } = MODULES;
const logger = initLogger({ logLevel: 'DEBUG' });
// async/await を使って書き換える
const response = await fetch("http://example.com/movies.json");
const resData = await response.json();
logger.log(resData);
}

Craft Functions の制約

Craft Functionsには次の制約があります。

  • Craft Functions実行時に渡せる入力データの最大サイズは、512KBです。
    • 入力データのサイズは、UTF-8エンコードのJSON文字列として計算します。
    • ※ 2025年10月以前からKARTE Craftをご利用いただいているプロジェクトでは、入力データの最大サイズが10KBに制限されている場合があります
  • Craft Functionsの1実行あたりの実行時間の上限は、ファンクションのタイプによって異なります。
    • HTTPタイプ: 3600秒(60分)
    • イベント駆動タイプ: 540秒(9分)
    • ※ 2025年10月以前からKARTE Craftをご利用いただいているプロジェクトでは、ファンクションのタイプに依らず1実行あたりの実行時間の上限が10秒に制限されている場合があります
    • タイムアウトの計測はリクエストの受信から始まり、コールドスタートに要する時間も含まれます
  • Craft Functionsはリクエスト量に応じて自動スケールしますが、無制限に処理できるわけではありません。安定して実行できる処理力については Craft Functions の処理力の目安 をご確認ください。
  • Craft Functionsのメモリサイズの上限は256MiBです。これを超えるメモリを必要とする処理についてはお問い合わせください。
  • Craft FunctionsではNode.jsでサポートされているglobal objectの利用を一部制限しています(requireprocess など)。
  • デフォルトでCraft Functionsの実行環境のPublic IPアドレスは不定です。Public IPアドレスを固定する場合は固定IPアドレスオプションをご利用ください。

Craft Functions の処理力の目安

Craft Functionsは安定して実行できる処理力に目安があります。この目安を超えると処理遅延やエラーの可能性があります。そのため、余裕を持った設計をしてください。

次の処理力の目安は、プロジェクト内のすべてのファンクションの合計負荷として考慮してください。複数のファンクションを持つ場合、各ファンクション単位ではなく、全ファンクションの合計がこの目安の範囲内に収まるよう設計してください。

全ファンクションの合計で安定して処理できる目安は次の通りです。これらは目安であり保証値ではありませんが、いずれも下回る範囲でのご利用を推奨します。

  • 同時実行数の上限(ある瞬間に同時に動いている処理の数): 100 〜 600
    • 上限の目安は、負荷の増え方によって変わります
      • リクエストが短時間に急増する場合(例:キャンペーン開始直後の大量アクセス): 100程度
      • リクエストが時間をかけて段階的に増える場合(例:営業時間に従って徐々に増加、キャンペーン期間を通じて段階的に増加): 600程度
  • 秒間リクエスト数: 300程度

「同時実行数」とは、ある瞬間に処理中のリクエスト数のことです。例えば全ファンクション合計で秒間100件のリクエストが来ていて、各リクエストの処理に3秒かかる場合、常に約300件が同時に処理されていることになります。

なお、リトライが発生する場合、リトライされた処理も同時実行数に含まれます。そのため、見込みより多くの同時実行が起きる可能性を想定してください。

目安を超える規模での利用が見込まれる場合は、事前にご相談ください。利用状況に応じて、安定して処理できるよう実行環境を調整できる場合があります。

制約や処理力の目安を超えた場合のエラー

処理力の目安や実行時間の上限を超えた場合、呼び出し元に次のエラーレスポンスを返すことがあります。

  • 500 / 503: 過負荷により処理が失敗または拒否された場合
  • 502 / 504: 実行時間の上限を超えてタイムアウトした場合

これらのエラーはファンクション内のtry/catchでは捕捉できません。過負荷でリクエストが拒否された場合、ファンクションのコードは実行されません。タイムアウトした場合、ファンクションにエラーは通知されず、処理がどこまで実行されたかも保証されません(重複実行の例を参照)。これらのエラーに対処する場合は、リトライなどのエラーハンドリングを呼び出し元で実装してください。