Lambda Function URLsで実現するサーバーレスAPIの新しい選択肢と実装戦略

Lambda Function URLsで実現するサーバーレスAPIの新しい選択肢と実装戦略

最終更新日:2025年09月18日公開日:2025年09月18日
益子 竜与志
writer:益子 竜与志
XThreads

AWS Lambdaの「Function URLs」は、2022年4月にリリースされて以来、サーバーレスアーキテクチャの設計において重要な選択肢となっています。

API Gatewayを介さず、Lambda関数に直接HTTPSエンドポイントを付与できるこの機能は、シンプルなWebhookやマイクロサービスの実装において、コストと複雑性の削減を実現します。

本記事では、Function URLsの技術的特性から実践的な活用方法、そして従来のAPI Gatewayとの使い分けまで、エンジニアリング視点で詳しく解説します。

Lambda Function URLsで実現するサーバーレスAPIの新しい選択肢と実装戦略

Function URLsが生まれた背景と本質的な価値

AWS Lambdaでシンプルなエンドポイントを作りたいとき、これまでは必ずAPI Gatewayを経由する必要がありました。しかし実際の開発現場では、Webhookの受信口や社内ツールのバックエンドなど、API Gatewayの豊富な機能が不要なケースも多く存在します。

Lambda Function URLsは、こうしたニーズに応える形で2022年4月にリリースされました。この機能により、Lambda関数に対してhttps://<url-id>.lambda-url.<region>.on.awsという形式の固定URLが自動発行され、追加料金なしでHTTPSエンドポイントを持つことができるようになりました。

私がこの機能を初めて触った時の印象は、「やっと来たか」というものでした。多くのケースでAPI Gatewayは過剰であり、Function URLsの登場により、アーキテクチャの選択肢が大きく広がったと感じています。

AuthType [None] を使用する場合でも、関数のリソースベースのポリシーではパブリックアクセスを明示的に許可する必要があることに注意
AuthType [None] を使用する場合でも、関数のリソースベースのポリシーではパブリックアクセスを明示的に許可する必要があることに注意
数秒で、関数 URL は利用可能となる
数秒で、関数 URL は利用可能となる

Function URLsの技術的特性

認証方式とセキュリティモデル

Function URLsでは、2つの認証方式が選択できます。

AWSドキュメントによると、認証方式の選択肢は以下の通りです。

  • AWS_IAM:SigV4署名による認証が必須となり、AWS IAMによるアクセス制御が可能
  • NONE:認証なしで誰でもアクセス可能(ただしリソースベースポリシーでの制御は可能)

実際のプロダクション環境では、NONEを選択する場合でも、必ず「リソースベースポリシー」や前段のCDN、WAFなどで適切なアクセス制御を行うことが重要です。完全に公開されたエンドポイントは、DDoS攻撃やコスト攻撃の対象となるリスクがあります。

CORSの設定と管理

ブラウザからのアクセスを想定する場合、「CORS」(Cross-Origin Resource Sharing)の設定が必要になります。Function URLsでは、URL設定側でCORSを一括管理できるようになっています。

設定可能な主要パラメータは以下の通りです。

  • AllowOriginsで許可するオリジンを指定
  • AllowMethodsで許可するHTTPメソッドを定義
  • AllowHeadersでカスタムヘッダーの許可を設定
  • MaxAgeでプリフライトリクエストのキャッシュ時間を制御

引用:Creating and managing Lambda function URLs - AWS Lambda Function URLのCORSは、URL設定側で一括管理可能です。プリフライトではURL設定が優先され、二重設定は重複ヘッダー警告の原因になるため、URL側に集約することを推奨します。

スロットリングとスケーリング戦略

Function URLsのスロットリングは、「予約済み同時実行」(Reserved Concurrency)によって制御されます。これは非常に重要なポイントで、最大RPSは予約値の約10倍という目安があります。

表 Function URLsのスロットリング設定と期待値

予約済み同時実行

想定最大RPS

用途例

10

約100

開発・テスト環境

100

約1,000

中規模Webhook

500

約5,000

本番環境API

1,000

約10,000

高負荷サービス

この表は、一般的な目安を示したものです。実際のRPSは、関数の実行時間やメモリサイズ、処理内容によって変動するため、必ず実環境でのテストを行い、適切な値を設定する必要があります。

API Gatewayとの使い分け戦略

Function URLsが適している場面

私の経験上、Function URLsが特に効果を発揮するのは以下のようなケースです。

シンプルなWebhookレシーバーの実装では、Function URLsは最適な選択肢となります。GitHubやStripeなどの外部サービスからのWebhookを受け取る際、API Gatewayの豊富な機能は不要であることがほとんどです。

// Node.js でのウェブフックを処理するシンプルな関数コード
// 引用 : https://aws.amazon.com/jp/blogs/news/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-
function-microservices/

exports.handler = async (event) => {
    
    // (オプション) メソッドとクエリ文字列を取得
    const method = event.requestContext.http.method;
    const queryParam = event.queryStringParameters.myCustomParameter;
    console.log(`Received ${method} request with ${queryParam}`)
    
    // 署名とペイロードを取得
    const webhookSignature = event.headers.SignatureHeader;
    const webhookPayload = JSON.parse(event.body);
    
    try {
        validateSignature(webhookSignature); // 署名が無効である場合はスロー
        handleEvent(webhookPayload); // 処理エラーの場合はスロー
    } catch (error) {
        console.error(error)
        return {
            statusCode: 400,
            body: `Cannot process event: ${error}`,
        }
    }

    return {
        statusCode: 200, // デフォルト値
        body: JSON.stringify({
            received: true,
        }),
    };
};

社内ツールやマイクロサービスのバックエンドとして使用する場合も、Function URLsで十分なケースが多いです。特に、認証をIAMで管理できる環境では、AWS_IAM認証を使用することで、シンプルかつ安全な実装が可能になります。

API Gatewayを選ぶべき場面

一方で、以下のような要件がある場合は、API Gatewayを選択する方が適切です。

カスタムドメインが必須の場合、Function URLsは標準ドメイン形式しか提供していないため、API GatewayかCloudFrontの併用が必要になります。また、リクエスト/レスポンスの変換やバリデーション、使用プランによるレート制限、APIキーによる認証など、高度なAPI管理機能が必要な場合も、API Gatewayの選択が妥当です。

表 Function URLsとAPI Gatewayの機能比較

機能

Function URLs

API Gateway

追加料金

なし

あり

カスタムドメイン

非対応

対応

リクエスト変換

非対応

対応

使用プラン

非対応

対応

WAF統合

CloudFront経由

直接統合可能

レスポンスキャッシュ

非対応

対応

この比較表から分かるように、Function URLsはシンプルさと低コストを重視した設計になっています。複雑なAPI管理が必要な場合は、API Gatewayの採用を検討すべきです。

実装例:TypeScriptでのFunction URLs活用

基本的な実装パターン

Function URLsを使用したLambda関数の実装例を見てみます。以下は、TypeScriptでシンプルなAPIエンドポイントを実装する例です。

import { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from 'aws-lambda';

interface RequestBody {
  name: string;
  email: string;
}

export const handler = async (
  event: APIGatewayProxyEventV2
): Promise<APIGatewayProxyResultV2> => {
  // リクエストメソッドの確認
  if (event.requestContext.http.method !== 'POST') {
    return {
      statusCode: 405,
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ error: 'Method Not Allowed' }),
    };
  }

  try {
    // リクエストボディのパース
    const body: RequestBody = JSON.parse(event.body || '{}');

    // バリデーション
    if (!body.name || !body.email) {
      return {
        statusCode: 400,
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ error: 'Invalid request body' }),
      };
    }

    // ビジネスロジックの実行
    const result = await processUserData(body);

    return {
      statusCode: 200,
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        message: 'Success',
        data: result
      }),
    };
  } catch (error) {
    console.error('Error processing request:', error);
    return {
      statusCode: 500,
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ error: 'Internal Server Error' }),
    };
  }
};

async function processUserData(data: RequestBody): Promise<object> {
  // ビジネスロジックの実装
  return {
    id: Math.random().toString(36).substring(7),
    ...data,
    createdAt: new Date().toISOString(),
  };
}

このコードで注目すべきは、Function URLsがAPI Gateway Payload v2.0形式のイベントを使用する点です。event.requestContext.http.methodでHTTPメソッドを取得し、event.bodyでリクエストボディにアクセスできます。

レスポンスストリーミングの実装

大量のデータを返す場合や、生成系AIの出力を逐次返却したい場合は、「レスポンスストリーミング」が有効です。

import { streamifyResponse } from 'lambda-stream';
import { Readable } from 'stream';

export const handler = streamifyResponse(async (event, responseStream, context) => {
  const pipeline = new Readable({
    async read() {
      // データを段階的に生成
      for (let i = 0; i < 10; i++) {
        const chunk = JSON.stringify({
          index: i,
          timestamp: Date.now()
        }) + '\\\\n';

        this.push(chunk);

        // 処理の間隔を設ける(実際の処理を模擬)
        await new Promise(resolve => setTimeout(resolve, 100));
      }

      // ストリームの終了
      this.push(null);
    }
  });

  // レスポンスヘッダーの設定
  responseStream.setContentType('application/x-ndjson');

  // パイプラインの実行
  pipeline.pipe(responseStream);
});

レスポンスストリーミングを使用することで、TTFB(Time To First Byte)を大幅に短縮できます。特に、大規模なデータセットを扱う場合や、リアルタイムに近い応答が求められる場合に威力を発揮します。

運用における実践的なTips

監視とアラートの設定

Function URLsは、CloudWatchに専用のメトリクスを自動送信します。主要なメトリクスとその活用方法を整理すると以下のようになります。

UrlRequestCountは総リクエスト数を示し、トラフィック傾向の把握に使用します。Url4xxCountUrl5xxCountはそれぞれクライアントエラーとサーバーエラーの発生状況を監視するために重要です。これらのメトリクスを基に、適切なアラートを設定することで、問題の早期発見が可能になります。

セキュリティのベストプラクティス

Function URLsを本番環境で使用する際の、セキュリティに関する私の推奨事項は以下の通りです。

まず、公開が必要ない限りAWS_IAM認証を選択することです。これにより、AWS IAMの強力なアクセス制御メカニズムを活用できます。NONE認証を使用する場合でも、必ずリソースベースポリシーで最小限のアクセス許可を設定し、可能であればCloudFrontやWAFを前段に配置して、DDoS攻撃や不正アクセスから保護します。

コスト最適化の観点

Function URLsは追加料金が発生しないという大きなメリットがあります。API Gatewayと比較した場合のコスト削減効果を見積もってみます。

月間100万リクエストを処理する場合、API Gateway(REST API)では約3.5ドルの料金が発生しますが、Function URLsではこの費用がゼロになります。年間で考えると42ドルの削減となり、複数のエンドポイントを運用している場合は、さらに大きな効果が期待できます。

Infrastructure as Codeでの実装

CloudFormationでの定義

Function URLsをCloudFormationで定義する際の実装例を示します。

// CDK v2での実装例
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as nodejs from 'aws-cdk-lib/aws-lambda-nodejs';

export class FunctionUrlStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Lambda関数の作成
    const fn = new nodejs.NodejsFunction(this, 'MyFunction', {
      entry: 'src/handler.ts',
      handler: 'handler',
      runtime: lambda.Runtime.NODEJS_20_X,
      timeout: cdk.Duration.seconds(30),
      memorySize: 512,
      reservedConcurrentExecutions: 100, // スロットリング設定
    });

    // Function URLの作成
    const fnUrl = fn.addFunctionUrl({
      authType: lambda.FunctionUrlAuthType.AWS_IAM,
      cors: {
        allowedOrigins: ['<https://example.com>'],
        allowedMethods: [lambda.HttpMethod.GET, lambda.HttpMethod.POST],
        allowedHeaders: ['Content-Type', 'Authorization'],
        maxAge: cdk.Duration.hours(24),
      },
    });

    // URL出力
    new cdk.CfnOutput(this, 'FunctionUrl', {
      value: fnUrl.url,
      description: 'The URL of the Lambda function',
    });
  }
}

このCDKコードでは、予約済み同時実行を100に設定し、CORS設定も含めてFunction URLを構成しています。実際のプロジェクトでは、環境変数や設定値を外部化し、環境ごとに適切な値を設定することが重要です。

私の考察

Function URLsは、サーバーレスアーキテクチャにおける重要な進化だと考えています。API Gatewayという中間層を省略できることで、レイテンシの削減とコストの最適化が実現されました。

今後期待される機能拡張として、カスタムドメインのネイティブサポートやVPCエンドポイント経由でのプライベートアクセスなどが挙げられます。これらが実現されれば、Function URLsの適用範囲はさらに広がるでしょう。

また、エッジコンピューティングの文脈でも、Function URLsは重要な役割を果たす可能性があります。Lambda@Edgeとの連携や、将来的にはリージョン間レプリケーションなども視野に入ってくるかもしれません。

まとめ

Lambda Function URLsは、「シンプルさ」と「費用対効果」を重視したサーバーレスエンドポイントの実装において、最適な選択肢となりました。API Gatewayが提供する高度な機能が不要な場合、Function URLsを採用することで、アーキテクチャの複雑性を減らし、運用コストを削減できます。

実装時のポイントをまとめると以下のようになります。

  • 認証方式は要件に応じて適切に選択し、セキュリティを最優先に考える
  • 予約済み同時実行でスロットリングを制御し、想定外のトラフィックから保護する
  • CloudWatchメトリクスを活用した監視体制を構築する
  • 必要に応じてCloudFrontやWAFと組み合わせて利用する

Function URLsとAPI Gatewayは競合するものではなく、それぞれが得意とする領域があります。プロジェクトの要件を正確に把握し、適材適所で使い分けることが、効率的なサーバーレスアーキテクチャ構築の鍵となります。

私自身、複数のプロジェクトでFunction URLsを活用してきましたが、その簡潔さと実用性は有用だと感じていますが、ただし、業務システムやアプリケーションにおける大規模なAPIの管理には不向きだという事を確実に念頭に扱いましょう。

複雑な認証・認可を伴うAPIの実装は、APIGatewayあるいはAppSyncを使用するのがベターです。

Careerバナーconsultingバナー