🙂

[AWS SAM]REST APIのメソッドとLambda関数をN:1にするには?

2023/06/17に公開

はじめに


AWS SAMのテンプレートで、REST APIの複数メソッド(PUT/GET/POST/DELETEなど)に対して1つのLambda関数とする場合にどのように書くのか?
マネジメントコンソールであれば、用意したLambda関数を各APIに紐づけてあげるだけなのですが、なかなか情報がなかったのですがようやく分かりました。

REST APIのメソッドとLambda関数を1:1にする

以下、REST APIのメソッドとLambda関数を1:1にする場合の例です。

Resources:
  ToDoCreateFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: todo/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
      - x86_64
      FunctionName: todo_create
      Policies:
        DynamoDBCrudPolicy:
          TableName: !Ref TodoTable
      Events:
        ToDo:
          Type: Api 
          Properties:
            Path: /todo
            Method: post
      Layers:
        - !Ref ToDoLayer
  ToDoReadFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: todo/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
      - x86_64
      FunctionName: todo_read
      Policies:
        DynamoDBCrudPolicy:
          TableName: !Ref TodoTable
      Events:
        ToDo:
          Type: Api 
          Properties:
            Path: /todo
            Method: get
      Layers:
        - !Ref ToDoLayer
  ToDoUpdateFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: todo/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
      - x86_64
      FunctionName: todo_update
      Policies:
        DynamoDBCrudPolicy:
          TableName: !Ref TodoTable
      Events:
        ToDo:
          Type: Api 
          Properties:
            Path: /todo
            Method: put
      Layers:
        - !Ref ToDoLayer
  ToDoDeleteFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: todo/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
      - x86_64
      FunctionName: todo_delete
      Policies:
        DynamoDBCrudPolicy:
          TableName: !Ref TodoTable
      Events:
        ToDo:
          Type: Api 
          Properties:
            Path: /todo
            Method: delete
      Layers:
        - !Ref ToDoLayer
・・・

例のようにREST APIの複数メソッドで共通のLambda関数のコード(app.lambda_handlerでメソッドごとの分岐を行う)を使用するような場合、
REST APIのメソッドとLambda関数を1:1で構築することは疎結合の観点では良いかもしれませんが、パッケージサイズが膨大になるなど弊害があると思います。
単純にサイズが4倍になりますので、私の環境では、たいしたコード量、たいしたモジュール量ではないのに、

Lambda 関数「xxx」のデプロイパッケージが大きすぎて、インラインコード編集を有効にできません。ただし、関数を呼び出すことはできます。

となったり、開発のしにくさからもあまり1:1にはしたくないと考えています。

REST APIのメソッドとLambda関数をN:1にする

以下、REST APIのメソッドとLambda関数をN:1にする場合の書き方です。

Resources:
  ToDoFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: todo/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
      - x86_64
      FunctionName: todo
      Policies:
        DynamoDBCrudPolicy:
          TableName: !Ref TodoTable
      Events:
        # メソッドごとに追記↓
        ToDoCreate:
          Type: Api 
          Properties:
            Path: /todo
            Method: post
        ToDoRead:
          Type: Api 
          Properties:
            Path: /todo
            Method: get
        ToDoUpdate:
          Type: Api 
          Properties:
            Path: /todo
            Method: put
        ToDoDelete:
          Type: Api 
          Properties:
            Path: /todo
            Method: delete
        # メソッドごとに追記↑

最後に

REST APIの各メソッドとLambda関数を1:1にするか、N:1にするか、システム全体で見てどちらが最善か選択すればよいと思います。
Lambda関数自体を別とすることでパフォーマンス向上はしますが、共通のモジュールを複数使っている場合や、共通処理が多い場合、関数を別とすることでパッケージサイズが大きくなるなどデメリットもあると思います。
比較的コード量が少なめであれば分けずに共通のコード、関数の方が良いのかな、と考えます。

参考

AWS SAMテンプレートでREST APIの複数メソッドをひとつのLambdaに統合するには?

Discussion