C#でAWS Lambdaを始める方法|作成・デプロイ・実行エラー解決まで初心者向けに解説
はじめに
C#でAWS Lambdaを使えるようになると、サーバーを用意せずに小さな処理をクラウド上で実行できます。たとえば、S3にファイルがアップロードされたら画像を変換する、DynamoDBにデータを書き込む、API Gateway経由でWeb APIを作る、定期実行でバッチ処理を動かす、といった用途に向いています。
一方で、初心者がC#でAWS Lambdaを始めると、「C#のラムダ式とAWS Lambdaの違いが分からない」「Handlerの指定でエラーになる」「ローカルでは動くのにAWS上では動かない」「デプロイ後に変更が反映されない」といったポイントでつまずきやすいです。
この記事では、C#でAWS Lambdaを作成し、ローカルでテストし、AWSへデプロイし、実行エラーを解決するまでの流れを初心者向けに解説します。2026年6月時点で、AWS Lambdaの.NET向けマネージドランタイムには.NET 10と.NET 8があり、.NET 9はコンテナイメージのみ対応という位置づけです。AWS ドキュメント
1. C#でAWS Lambdaを始める前に知っておきたい基礎
1-1. AWS Lambdaとは?サーバー管理なしでC#コードを実行できる仕組み
AWS Lambdaは、サーバーの構築やOS管理をせずにコードを実行できるサーバーレスコンピューティングサービスです。開発者はC#などで関数を書き、イベントをきっかけに実行します。Lambdaのランタイムは、呼び出しイベント、コンテキスト情報、戻り値を関数との間で受け渡す役割を持ちます。AWS ドキュメント
通常のサーバー運用では、仮想マシンの作成、OSアップデート、ミドルウェア設定、スケーリング、障害対応などを考える必要があります。しかしAWS Lambdaでは、関数単位でコードを配置し、必要なときだけ実行できます。アクセスが増えた場合も、Lambda側でスケールするため、小規模なAPIやイベント駆動処理を始めやすいのが特徴です。
C#でAWS Lambdaを使う場合、主に次のような形で処理を作ります。
C#using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace MyLambda;
public class Function
{
public string FunctionHandler(string input, ILambdaContext context)
{
context.Logger.LogInformation($"Input: {input}");
return input.ToUpper();
}
}
この例では、FunctionHandlerがLambda関数として呼び出されるメソッドです。AWS Lambdaにイベントが渡されると、指定したHandlerが実行され、戻り値が呼び出し元に返されます。
1-2. 「C#のラムダ式」と「AWS Lambda」の違い
C#で「lambda」と聞くと、まずラムダ式を思い浮かべる人も多いでしょう。C#のラムダ式は、匿名関数を簡潔に書くための構文です。
C#var numbers = new[] { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(x => x % 2 == 0);
ここでのx => x % 2 == 0がC#のラムダ式です。LINQやイベント処理、コールバックなどでよく使われます。
一方、AWS LambdaはAWSのサーバーレス実行サービスです。名前に「Lambda」とありますが、C#のラムダ式そのものを指しているわけではありません。C#のラムダ式は言語機能、AWS Lambdaはクラウド上でコードを実行するサービスです。
混同しやすいですが、次のように整理すると分かりやすいです。
| 種類 | 意味 | 例 |
|---|---|---|
| C#のラムダ式 | C#の文法 | x => x * 2 |
| AWS Lambda | AWSのサーバーレス実行環境 | S3イベントでC#関数を実行 |
| C# Lambda関数 | AWS Lambda上で動くC#コード | FunctionHandlerメソッド |
この記事で扱う「C# Lambda」は、C#で書いたコードをAWS Lambda上で実行する方法を指します。
1-3. C#でAWS Lambdaを使うメリット・向いているケース
C#でAWS Lambdaを使うメリットは、既存の.NET資産やC#の型安全な開発体験を活かしながら、サーバーレス構成を作れることです。特に、社内システムや業務アプリでC#や.NETを使っているチームにとっては、学習コストを抑えながらAWSのイベント駆動アーキテクチャを導入できます。
C# Lambdaが向いているケースは次のとおりです。
| 用途 | 例 |
|---|---|
| 軽量なAPI | API Gateway + Lambdaで問い合わせAPIを作る |
| ファイル処理 | S3アップロードをきっかけに画像変換やCSV解析を行う |
| 定期実行 | EventBridgeで毎日決まった時間に処理を実行する |
| データ連携 | DynamoDB、SQS、SNS、Step Functionsと組み合わせる |
| 既存.NET資産の活用 | 共通ライブラリやドメインロジックをLambdaで再利用する |
反対に、常時接続が必要な処理、非常に長時間実行する処理、起動時間に厳しいリアルタイム処理、大量のローカル状態を保持する処理には向かない場合があります。
1-4. 初心者がつまずきやすいポイント
C#でAWS Lambdaを始める初心者がつまずきやすいポイントは、主に次の5つです。
1つ目は、Handlerの指定ミスです。Lambdaでは、どのアセンブリの、どのクラスの、どのメソッドを実行するかをHandlerとして指定します。この形式が間違っていると、Handler not foundやUnable to load type from assemblyが発生します。
2つ目は、IAM権限の不足です。LambdaからS3やDynamoDBにアクセスする場合、実行ロールに必要な権限が付与されていなければAccessDeniedExceptionが発生します。
3つ目は、JSONの入力形式です。C#のクラスとテストイベントJSONのプロパティ名や型が合っていないと、期待した値が入らなかったり、シリアライズエラーになったりします。
4つ目は、ローカル環境とAWS環境の違いです。ローカルでは環境変数や認証情報が存在していても、AWS上のLambdaには設定されていないことがあります。
5つ目は、デプロイ設定の見落としです。関数名、リージョン、ランタイム、IAMロール、Handler、タイムアウト、メモリなどが意図した設定になっていないと、コード自体は正しくても実行に失敗します。
2. C#でAWS Lambdaを開発するために必要な準備
2-1. 必要なAWSアカウント・IAM権限
C#でAWS Lambdaを作るには、まずAWSアカウントが必要です。学習用であっても、課金が発生する可能性があるため、請求アラートや予算設定を先に行っておくと安心です。
開発時に必要になる代表的なIAM権限は次のとおりです。
| 操作 | 必要な権限の例 |
|---|---|
| Lambda関数の作成・更新 | lambda:CreateFunction, lambda:UpdateFunctionCode, lambda:UpdateFunctionConfiguration |
| IAMロールの参照・付与 | iam:GetRole, iam:PassRole |
| CloudWatch Logsの確認 | logs:DescribeLogGroups, logs:DescribeLogStreams, logs:GetLogEvents |
| S3連携 | s3:GetObject, s3:PutObject |
| DynamoDB連携 | dynamodb:GetItem, dynamodb:PutItem, dynamodb:Query |
初心者の場合、最初は管理者権限で進めたくなるかもしれません。しかし実務では、必要な操作だけを許可する最小権限の考え方が重要です。特にLambdaの実行ロールには、関数が本当に必要とするAWSサービスへのアクセス権だけを付与するようにします。
2-2. .NET SDK・AWS CLI・Amazon.Lambda.Toolsの準備
C#でAWS Lambdaを開発するには、主に次のツールを用意します。
| ツール | 役割 |
|---|---|
| .NET SDK | C#プロジェクトの作成、ビルド、テスト |
| AWS CLI | AWS認証情報やリージョンの設定、AWS操作 |
| Amazon.Lambda.Tools | .NET CLIからLambdaの作成・デプロイを行う |
| Amazon.Lambda.Templates | Lambda用の.NETプロジェクトテンプレート |
AWS公式ドキュメントでは、.NET CLIとAmazon.Lambda.Toolsを使って.NETベースのLambdaアプリケーションを作成、パッケージ化、デプロイする方法が案内されています。AWS ドキュメント
インストール例は次のとおりです。
Bashdotnet --version
aws --version
Amazon.Lambda.Toolsをグローバルツールとしてインストールします。
Bashdotnet tool install -g Amazon.Lambda.Tools
すでにインストール済みの場合は更新します。
Bashdotnet tool update -g Amazon.Lambda.Tools
Lambda用テンプレートもインストールします。
Bashdotnet new install Amazon.Lambda.Templates
利用できるテンプレートは次のコマンドで確認できます。
Bashdotnet new list lambda
2-3. Visual Studio/VS Code/Riderの選び方
C# Lambdaの開発環境は、Visual Studio、VS Code、Riderのいずれでも構築できます。
Visual Studioは、Windows環境でC#開発に慣れている人に向いています。AWS Toolkit for Visual Studioを使うと、IDE上からLambdaの作成やデプロイを行いやすくなります。
VS Codeは、軽量でクロスプラットフォームに使える点が魅力です。C# Dev Kit、AWS Toolkit、.NET SDK、AWS CLIを組み合わせれば、MacやLinuxでもC# Lambdaを開発できます。
Riderは、JetBrains製IDEに慣れている人や、リファクタリング機能、ナビゲーション、テスト実行の使いやすさを重視する人に向いています。
初心者には、次の選び方がおすすめです。
| 状況 | おすすめ |
|---|---|
| WindowsでC#中心に開発する | Visual Studio |
| MacやLinuxでも使いたい | VS Code |
| JetBrains製品に慣れている | Rider |
| チームでCLI運用したい | エディタは自由、デプロイはdotnet lambdaに統一 |
重要なのは、IDEに依存しすぎないことです。実務ではCI/CDでビルドやデプロイを行うことが多いため、dotnet build、dotnet test、dotnet lambda deploy-functionなどのCLI操作に慣れておくと役立ちます。
2-4. 対応する.NETランタイムの確認方法
C# Lambdaを作る前に、AWS Lambdaが対応している.NETランタイムを確認しましょう。2026年6月時点では、AWS Lambdaの.NET向けランタイムとして.NET 10はdotnet10、.NET 8はdotnet8という識別子で扱われます。また、.NET 9はコンテナイメージのみの対応です。AWS ドキュメント
Microsoft側のサポートライフサイクルも確認しておく必要があります。.NET 10は2028年11月まで、.NET 8は2026年11月までサポートされる予定です。Microsoft Learn
新規でC# Lambdaを始める場合は、基本的に.NET 10を選ぶのが自然です。ただし、既存プロジェクトが.NET 8で安定稼働している場合や、利用しているライブラリが.NET 10に未対応の場合は、無理に移行せず検証してから切り替えます。
確認すべきポイントは次のとおりです。
| 確認項目 | 見るべき内容 |
|---|---|
| AWS Lambdaの対応 | 対象ランタイムがAWS Lambdaで使えるか |
| Microsoftのサポート | .NETのサポート終了日 |
| NuGetパッケージ | 使用ライブラリが対象.NETに対応しているか |
| デプロイ方式 | ZIPデプロイかコンテナイメージか |
| 実行環境 | x86_64かarm64か |
2-5. AWS認証情報とリージョンの設定
ローカルからLambdaをデプロイするには、AWS CLIに認証情報とリージョンを設定します。
Bashaws configure
入力する内容は次のとおりです。
AWS Access Key ID [None]: <アクセスキー>
AWS Secret Access Key [None]: <シークレットアクセスキー>
Default region name [None]: ap-northeast-1
Default output format [None]: json
東京リージョンを使う場合はap-northeast-1を指定します。学習用の記事では東京リージョンで進めることが多いですが、実務では利用者に近いリージョン、社内規定、連携サービスの配置、可用性要件などを踏まえて選びます。
設定確認は次のコマンドで行えます。
Bashaws sts get-caller-identity
このコマンドでアカウントIDやARNが表示されれば、AWS認証情報は正しく設定されています。
3. C#のAWS Lambda関数を作成する手順
3-1. .NET Lambdaテンプレートをインストールする
C# Lambda関数を最初から手書きで作ることもできますが、初心者は公式テンプレートを使うのがおすすめです。テンプレートを使うと、Function.cs、テストプロジェクト、設定ファイルが自動生成されるため、Lambda特有の構成を理解しやすくなります。
テンプレートをインストールします。
Bashdotnet new install Amazon.Lambda.Templates
テンプレート一覧を確認します。
Bashdotnet new list lambda
代表的なテンプレートには、空の関数、S3イベント用、DynamoDBイベント用、API Gateway用、ASP.NET Core Web API用などがあります。
最初はシンプルな空のLambda関数テンプレートを選ぶとよいでしょう。いきなりAPI GatewayやS3イベントから始めると、Lambda本体以外の設定も必要になり、原因切り分けが難しくなります。
3-2. C# Lambdaプロジェクトを作成する
シンプルなC# Lambdaプロジェクトを作成します。
Bashdotnet new lambda.EmptyFunction -n MyCSharpLambda
cd MyCSharpLambda
作成後の構成は、おおむね次のようになります。
MyCSharpLambda/
├─ src/
│ └─ MyCSharpLambda/
│ ├─ Function.cs
│ ├─ MyCSharpLambda.csproj
│ └─ aws-lambda-tools-defaults.json
└─ test/
└─ MyCSharpLambda.Tests/
├─ FunctionTest.cs
└─ MyCSharpLambda.Tests.csproj
src配下にLambda本体、test配下に単体テストが作成されます。まずは生成された状態のままビルドします。
Bashdotnet build
テストも実行します。
Bashdotnet test
ここまで成功すれば、C# Lambda関数の土台はできています。
3-3. Function.cs・Handler・aws-lambda-tools-defaults.jsonの役割
Function.csは、Lambdaで実行されるC#コードを書く中心的なファイルです。
C#using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace MyCSharpLambda;
public class Function
{
public string FunctionHandler(string input, ILambdaContext context)
{
return input.ToUpper();
}
}
FunctionHandlerが実行対象のメソッドです。AWS Lambdaでは、このメソッドをHandlerとして指定します。一般的なHandler指定は次の形式です。
アセンブリ名::名前空間.クラス名::メソッド名
たとえば次のようになります。
MyCSharpLambda::MyCSharpLambda.Function::FunctionHandler
AWS公式ドキュメントでも、C#のLambdaハンドラーではアセンブリ、型、メソッドを正しく指定することが重要とされています。Handler指定の誤りは、C# Lambdaで最も多い実行エラーの1つです。AWS ドキュメント
aws-lambda-tools-defaults.jsonは、dotnet lambdaコマンドで使うデプロイ設定ファイルです。関数名、ランタイム、メモリ、タイムアウト、Handler、リージョンなどを定義します。
JSON{
"profile": "default",
"region": "ap-northeast-1",
"configuration": "Release",
"function-runtime": "dotnet10",
"function-memory-size": 256,
"function-timeout": 30,
"function-handler": "MyCSharpLambda::MyCSharpLambda.Function::FunctionHandler"
}
このファイルの設定が実際のプロジェクト名やランタイムとズレていると、デプロイや実行でエラーになります。
3-4. 入力イベントと戻り値の基本
Lambda関数は、イベントを受け取り、処理結果を返します。入力と戻り値は、文字列、数値、クラス、ストリームなどさまざまな形にできます。
シンプルな文字列入力の例です。
C#public string FunctionHandler(string input, ILambdaContext context)
{
return $"Hello, {input}";
}
JSONをC#クラスで受け取る例です。
C#public class Request
{
public string Name { get; set; } = "";
public int Age { get; set; }
}
public class Response
{
public string Message { get; set; } = "";
}
public Response FunctionHandler(Request request, ILambdaContext context)
{
return new Response
{
Message = $"{request.Name}さんは{request.Age}歳です"
};
}
テストイベントJSONは次のようになります。
JSON{
"name": "Taro",
"age": 30
}
C#ではプロパティ名がName、JSONではnameになっています。この対応はシリアライザーの設定によって変わるため、意図したマッピングになっているか確認しましょう。
3-5. JSONシリアライズ設定の考え方
C# LambdaでJSONを扱う場合、シリアライズ設定は重要です。Lambdaテンプレートでは、次のようにSystem.Text.Jsonベースのシリアライザーを指定することがあります。
C#[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
この指定により、Lambdaの入力JSONがC#オブジェクトへ変換され、戻り値のC#オブジェクトがJSONへ変換されます。
実務では、次の点を意識します。
| ポイント | 内容 |
|---|---|
| プロパティ名 | JSONのcamelCaseとC#のPascalCaseの対応 |
| null許容 | 入力値が欠けた場合の扱い |
| 日付型 | タイムゾーンやフォーマット |
| enum | 文字列で受けるか数値で受けるか |
| 破壊的変更 | API利用者に影響するJSON構造変更を避ける |
初心者は、まず入力クラスとテストイベントJSONを小さく作り、1つずつ動作確認するのがおすすめです。複雑なJSONを一度に扱おうとすると、どのプロパティで変換に失敗したのか分かりにくくなります。
4. ローカル環境でC# Lambdaを実行・テストする方法
4-1. dotnet testで単体テストを実行する
Lambda関数も通常のC#コードと同じように単体テストできます。テンプレートから作成したプロジェクトには、テストプロジェクトが含まれていることが多いです。
Bashdotnet test
テストコードの例です。
C#using Xunit;
using Amazon.Lambda.TestUtilities;
namespace MyCSharpLambda.Tests;
public class FunctionTest
{
[Fact]
public void TestToUpperFunction()
{
var function = new Function();
var context = new TestLambdaContext();
var result = function.FunctionHandler("hello", context);
Assert.Equal("HELLO", result);
}
}
TestLambdaContextを使うと、Lambda実行時に渡されるILambdaContextをテスト用に再現できます。
単体テストでは、AWSに接続しなくても確認できる処理を重点的にテストします。たとえば、入力チェック、変換処理、業務ロジック、エラーハンドリングなどです。
4-2. Mock Lambda Test Toolで動作確認する
AWS Lambdaには、.NET Lambda関数をローカルで試すためのMock Lambda Test Toolがあります。ブラウザ画面からテストイベントJSONを入力して、Lambda関数の動作を確認できます。
インストール例です。
Bashdotnet tool install -g Amazon.Lambda.TestTool-10.0
プロジェクトのsrc配下へ移動して実行します。
Bashdotnet lambda-test-tool-10.0
ブラウザが起動し、テストイベントを入力して関数を実行できます。AWS上にデプロイする前に、Handler、入力JSON、戻り値、ログ出力を確認できるため、初心者には非常に便利です。
.NET 8を使っている場合は、対応するバージョンのTest Toolを利用します。
Bashdotnet tool install -g Amazon.Lambda.TestTool-8.0
プロジェクトのランタイムとテストツールのバージョンを合わせることが大切です。
4-3. テストイベントJSONの作り方
C# LambdaのテストイベントJSONは、Handlerの引数に合わせて作ります。
たとえば、Handlerが次のようなクラスを受け取る場合です。
C#public class OrderRequest
{
public string OrderId { get; set; } = "";
public decimal Amount { get; set; }
}
テストイベントJSONは次のようになります。
JSON{
"orderId": "A001",
"amount": 1500
}
API Gatewayから呼び出されるLambdaの場合は、単純なJSONではなく、API Gatewayのイベント構造に合わせる必要があります。
C#using Amazon.Lambda.APIGatewayEvents;
public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
{
return new APIGatewayProxyResponse
{
StatusCode = 200,
Body = "Hello from Lambda"
};
}
この場合、テストイベントにはhttpMethod、path、headers、bodyなどが含まれます。S3イベント、EventBridgeイベント、SQSイベントなども、それぞれイベント構造が異なります。
初心者は、まず「自分のHandlerが何を引数に取っているか」を確認し、その型に合うJSONを作ることから始めましょう。
4-4. ローカル実行とAWS上の実行で違いが出る理由
ローカルでは成功するのにAWS上では失敗することがあります。原因は、実行環境が完全には同じではないためです。
代表的な違いは次のとおりです。
| 違い | 例 |
|---|---|
| 環境変数 | ローカルにはあるがLambdaには未設定 |
| IAM権限 | ローカルのAWS認証情報では成功するがLambda実行ロールでは拒否される |
| ファイルパス | ローカルのパスとLambdaのパスが違う |
| タイムアウト | ローカルでは待てるがLambdaでは設定秒数で終了する |
| ネットワーク | VPC設定やセキュリティグループで接続できない |
| ランタイム | ローカルの.NET SDKとLambdaランタイムが違う |
この差を減らすには、環境変数、リージョン、IAMロール、入力イベント、ランタイムバージョンをできるだけ明示的に管理します。また、CloudWatch Logsに必要な情報を出力し、AWS上で何が起きているかを確認できるようにしましょう。
5. C# LambdaをAWSへデプロイする方法
5-1. dotnet lambda deploy-functionでデプロイする
C# LambdaをAWSへデプロイする基本コマンドは次のとおりです。
Bashdotnet lambda deploy-function MyCSharpLambda
初回デプロイ時には、ランタイム、IAMロール、メモリ、タイムアウトなどの入力を求められることがあります。aws-lambda-tools-defaults.jsonに設定を書いておくと、毎回の入力を減らせます。
設定例です。
JSON{
"profile": "default",
"region": "ap-northeast-1",
"configuration": "Release",
"function-runtime": "dotnet10",
"function-memory-size": 256,
"function-timeout": 30,
"function-handler": "MyCSharpLambda::MyCSharpLambda.Function::FunctionHandler"
}
デプロイ時には、プロジェクトがビルドされ、必要なファイルがパッケージ化され、Lambda関数へアップロードされます。
5-2. Lambda関数名・リージョン・ランタイム・IAMロールの指定
デプロイ時に特に重要な設定は、関数名、リージョン、ランタイム、IAMロールです。
| 設定 | 例 | 注意点 |
|---|---|---|
| 関数名 | MyCSharpLambda | 環境ごとに命名規則を決める |
| リージョン | ap-northeast-1 | デプロイ先を間違えない |
| ランタイム | dotnet10 | プロジェクトのターゲットフレームワークと合わせる |
| IAMロール | lambda-basic-role | 必要な権限を付与する |
| Handler | Assembly::Namespace.Class::Method | 文字列ミスに注意する |
csprojのターゲットフレームワークも確認します。
XML<TargetFramework>net10.0</TargetFramework>
.NET 8を使う場合は次のようになります。
XML<TargetFramework>net8.0</TargetFramework>
csproj、aws-lambda-tools-defaults.json、AWS Lambda側のランタイム設定がズレていると、ビルドや実行で問題が起きます。
5-3. AWSコンソールでデプロイ結果を確認する
デプロイが完了したら、AWSマネジメントコンソールでLambda関数を確認します。
確認する項目は次のとおりです。
| 確認項目 | 見る場所 |
|---|---|
| 関数名 | Lambda関数一覧 |
| ランタイム | ランタイム設定 |
| Handler | ランタイム設定またはコード設定 |
| メモリ | 一般設定 |
| タイムアウト | 一般設定 |
| 実行ロール | アクセス権限 |
| 環境変数 | 設定タブ |
| 最新更新日時 | コードタブ |
デプロイ後に想定と違う動きをする場合、まずリージョンを確認してください。CLIでは東京リージョンにデプロイしたつもりでも、コンソールで別リージョンを見ていると関数が見つかりません。
5-4. ZIPデプロイとコンテナイメージデプロイの違い
C# Lambdaのデプロイ方式には、大きく分けてZIPデプロイとコンテナイメージデプロイがあります。
ZIPデプロイは、ビルドした成果物をZIP形式でアップロードする方式です。シンプルで始めやすく、一般的なC# Lambda関数ではまずZIPデプロイから始めるのがおすすめです。
コンテナイメージデプロイは、DockerイメージとしてLambda関数を作成する方式です。OSレベルの依存関係がある場合、大きなライブラリを含めたい場合、マネージドランタイムにないバージョンや構成を使いたい場合に向いています。
| 比較項目 | ZIPデプロイ | コンテナイメージデプロイ |
|---|---|---|
| 始めやすさ | 高い | やや難しい |
| Docker知識 | 不要 | 必要 |
| カスタマイズ性 | 標準的 | 高い |
| 運用負荷 | 低め | イメージ管理が必要 |
| 初心者向け | 向いている | 慣れてからがおすすめ |
最初のC# LambdaではZIPデプロイを選び、必要になったらコンテナイメージを検討するとよいでしょう。
5-5. 再デプロイ時に確認すべき設定
コードを変更して再デプロイしたのに反映されない場合、次の点を確認します。
| 確認項目 | 内容 |
|---|---|
| デプロイ先リージョン | 見ているリージョンとデプロイ先が同じか |
| 関数名 | 別の関数へデプロイしていないか |
| ビルド構成 | Releaseビルドが最新か |
| Handler | 古いクラス名・メソッド名を参照していないか |
| エイリアス | $LATESTではなく古いバージョンを参照していないか |
| API Gateway | ステージや統合先が古くないか |
| ブラウザ・クライアント | キャッシュされた結果を見ていないか |
特に、Lambdaのバージョンやエイリアスを使っている場合は注意が必要です。コードは更新されていても、API Gatewayや呼び出し元が古いバージョンを参照していると、変更が反映されていないように見えます。
6. AWS上でC# Lambdaを実行・確認する方法
6-1. AWSコンソールからテスト実行する
デプロイしたC# Lambdaは、AWSコンソールからテスト実行できます。Lambda関数の画面で「テスト」イベントを作成し、JSONを入力して実行します。
文字列入力の関数であれば、テストイベントは次のようにできます。
JSON"hello"
クラス入力の場合は次のようなJSONにします。
JSON{
"name": "Taro",
"age": 30
}
実行後、レスポンス、実行時間、課金対象時間、ログ出力などを確認できます。最初はコンソールから手動実行し、期待した結果が返るか確認しましょう。
6-2. CloudWatch Logsでログを確認する
C# Lambdaで問題が発生した場合、最初に見るべき場所はCloudWatch Logsです。ILambdaContextのLoggerを使うと、Lambda実行ログにメッセージを出力できます。
C#public string FunctionHandler(string input, ILambdaContext context)
{
context.Logger.LogInformation($"Received input: {input}");
return input.ToUpper();
}
ログには、開始、終了、実行時間、メモリ使用量、例外情報などが出力されます。エラー調査では、次の情報を確認します。
| ログ項目 | 確認内容 |
|---|---|
| START | 関数が呼び出されたか |
| END | 正常終了したか |
| REPORT | 実行時間、メモリ使用量 |
| 例外スタックトレース | エラー箇所 |
| 独自ログ | 入力値や処理状況 |
ログが多すぎると調査しにくいため、実務では必要な情報を構造化して出すことが重要です。ただし、個人情報、アクセストークン、パスワードなどの機密情報はログに出してはいけません。
6-3. API Gateway・S3・EventBridgeから起動する基本パターン
AWS Lambdaは、さまざまなAWSサービスのイベントから起動できます。
API Gatewayと組み合わせると、HTTPリクエストを受けるWeb APIを作れます。
クライアント → API Gateway → Lambda → レスポンス
S3と組み合わせると、ファイルアップロードをきっかけに処理できます。
S3にファイルアップロード → Lambda起動 → ファイル解析・変換
EventBridgeと組み合わせると、定期実行やイベントルールによる起動ができます。
毎日9時 → EventBridge → Lambda起動 → バッチ処理
C# Lambdaでよく使うイベント型は次のとおりです。
| 起動元 | NuGetパッケージ・型の例 |
|---|---|
| API Gateway | Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest |
| S3 | Amazon.Lambda.S3Events.S3Event |
| SQS | Amazon.Lambda.SQSEvents.SQSEvent |
| EventBridge | Amazon.Lambda.CloudWatchEvents系 |
| DynamoDB Streams | Amazon.Lambda.DynamoDBEvents |
最初はAPI GatewayかEventBridgeから始めると、動作を確認しやすいです。
6-4. 環境変数を使って設定値を管理する
C# Lambdaでは、接続先URL、テーブル名、バケット名、ログレベルなどの設定値を環境変数で管理できます。
AWSコンソールまたはCLIで環境変数を設定し、C#コードから読み取ります。
C#var tableName = Environment.GetEnvironmentVariable("TABLE_NAME");
if (string.IsNullOrEmpty(tableName))
{
throw new InvalidOperationException("TABLE_NAME is not set.");
}
環境変数を使うメリットは、コードを変更せずに環境ごとの設定を切り替えられることです。
| 環境 | TABLE_NAME |
|---|---|
| 開発 | orders-dev |
| 検証 | orders-stg |
| 本番 | orders-prod |
ただし、パスワードやAPIキーなどの機密情報をそのまま環境変数に入れるのは避け、AWS Secrets ManagerやAWS Systems Manager Parameter Storeの利用を検討します。
6-5. 実行時間・メモリ・タイムアウトの設定
Lambdaにはメモリサイズとタイムアウトの設定があります。C# Lambdaでは、コールドスタートやライブラリ読み込みの影響を受けることもあるため、処理内容に合わせて調整します。
| 設定 | 考え方 |
|---|---|
| メモリ | 少なすぎると処理が遅くなることがある |
| タイムアウト | 外部APIやDBアクセスがある場合は余裕を持たせる |
| リトライ | 非同期実行やイベントソースによって挙動が異なる |
| 同時実行数 | 急なアクセス増や下流サービス保護を考慮する |
たとえば、外部APIを呼び出す処理でタイムアウトを3秒にしていると、ネットワーク遅延だけで失敗する可能性があります。一方で、タイムアウトを長くしすぎると、障害時に無駄な実行時間が増えます。
実務では、CloudWatch Logsやメトリクスを見ながら、実行時間、エラー率、メモリ使用量をもとに調整します。
7. C# Lambdaでよくある実行エラーと解決方法
7-1. Handler not found/Unable to load type from assemblyの原因と対処
Handler not foundやUnable to load type from assemblyは、C# Lambdaで非常によくあるエラーです。多くの場合、Handlerの指定が実際のコードと一致していません。
確認するポイントは次のとおりです。
| 確認項目 | 例 |
|---|---|
| アセンブリ名 | MyCSharpLambda |
| 名前空間 | MyCSharpLambda |
| クラス名 | Function |
| メソッド名 | FunctionHandler |
| Handler文字列 | MyCSharpLambda::MyCSharpLambda.Function::FunctionHandler |
csprojのアセンブリ名が変更されている場合、Handlerの先頭も変わることがあります。
XML<AssemblyName>CustomAssemblyName</AssemblyName>
この場合、Handlerも次のように変更が必要です。
CustomAssemblyName::MyCSharpLambda.Function::FunctionHandler
また、クラスやメソッドをprivateにしている場合も呼び出せません。Lambdaから呼び出すHandlerは、基本的にpublicにします。
7-2. MissingMethodException・FileNotFoundExceptionの原因と対処
MissingMethodExceptionは、実行時に必要なメソッドが見つからない場合に発生します。ライブラリのバージョン不整合、古いDLLの参照、デプロイ成果物の不足などが原因です。
FileNotFoundExceptionは、必要なファイルやアセンブリがLambda環境に存在しない場合に発生します。
対処方法は次のとおりです。
Bashdotnet clean
dotnet restore
dotnet build -c Release
dotnet lambda deploy-function MyCSharpLambda
NuGetパッケージのバージョンも確認します。
Bashdotnet list package
ローカルで動くのにAWS上で失敗する場合、ローカルには存在するファイルをLambdaパッケージに含め忘れている可能性があります。設定ファイルやテンプレートファイルを使う場合は、csprojでコピー設定を確認します。
XML<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
ただし、Lambdaでは設定値をファイルではなく環境変数やParameter Storeで管理したほうが運用しやすいケースも多いです。
7-3. AccessDeniedExceptionが出る場合のIAM権限確認
AccessDeniedExceptionは、Lambda関数に付与されたIAMロールの権限が不足しているときに発生します。
たとえば、LambdaからS3オブジェクトを取得する場合、実行ロールに次のような権限が必要です。
JSON{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::example-bucket/*"
}
DynamoDBへ書き込む場合は、対象テーブルへのdynamodb:PutItemなどが必要です。
JSON{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem"
],
"Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/orders"
}
確認すべき点は次のとおりです。
| 確認項目 | 内容 |
|---|---|
| 実行ロール | Lambdaに正しいロールが設定されているか |
| アクション | 必要なAWS操作が許可されているか |
| リソースARN | 対象バケットやテーブルのARNが正しいか |
| リージョン | リソースが同じリージョンにあるか |
| 明示的Deny | SCPや権限境界で拒否されていないか |
初心者は、まずCloudWatch Logsのエラーメッセージに表示されるis not authorized to performの部分を読み、どのアクションが拒否されたのかを確認しましょう。
7-4. Task timed out afterが出る場合のタイムアウト対策
Task timed out afterは、Lambda関数が設定されたタイムアウト時間内に終了しなかった場合に発生します。
原因として多いのは次のようなものです。
| 原因 | 対策 |
|---|---|
| 外部APIの応答が遅い | HttpClientにタイムアウトを設定する |
| DB接続が遅い | 接続先、VPC、セキュリティグループを確認する |
| 無限ループ | ループ条件を見直す |
| 大量データ処理 | 分割処理やSQS利用を検討する |
| コールドスタート | 初期化処理を軽くする |
HttpClientを使う場合は、待ち続けないようにします。
C#private static readonly HttpClient HttpClient = new()
{
Timeout = TimeSpan.FromSeconds(5)
};
Lambdaのタイムアウトを延ばすだけでは根本解決にならない場合があります。どの処理で時間がかかっているかをログに出し、必要に応じて処理分割や非同期化を検討しましょう。
7-5. JSONの入力形式エラー・シリアライズエラーの解決
JSON関連のエラーは、入力イベントとC#クラスの形が合っていないときに起きます。
たとえば、C#側が数値を期待しているのに、JSONで文字列を渡しているケースです。
C#public class Request
{
public int Age { get; set; }
}
誤ったJSONです。
JSON{
"age": "thirty"
}
正しいJSONです。
JSON{
"age": 30
}
また、API Gateway経由ではbodyが文字列として渡されるため、さらにJSONデシリアライズが必要になることがあります。
C#var request = JsonSerializer.Deserialize<OrderRequest>(apiGatewayRequest.Body);
このとき、Bodyがnullや空文字の場合に備えてチェックします。
C#if (string.IsNullOrWhiteSpace(apiGatewayRequest.Body))
{
return new APIGatewayProxyResponse
{
StatusCode = 400,
Body = "Request body is empty."
};
}
JSONエラーを防ぐには、入力モデルを明確にし、テストイベントを保存し、正常系だけでなく異常系のテストも用意することが大切です。
7-6. ログが出ない・CloudWatchに表示されない場合の確認点
ログがCloudWatch Logsに表示されない場合は、次の点を確認します。
| 確認項目 | 内容 |
|---|---|
| Lambdaが実行されているか | そもそも呼び出しが発生しているか |
| リージョン | LambdaとCloudWatch Logsのリージョンが同じか |
| IAM権限 | 実行ロールにログ出力権限があるか |
| ロググループ | /aws/lambda/関数名が存在するか |
| ログ出力コード | context.Logger.LogInformationなどを書いているか |
| フィルタ | コンソールの時間範囲が適切か |
CloudWatch Logsを見るときは、時間範囲の指定にも注意してください。実行直後のログを見ているつもりでも、コンソール側の表示範囲が古い時間帯になっていると、ログがないように見えます。
また、LambdaがVPC内にあるかどうかはCloudWatch Logs出力とは直接関係しませんが、VPC内から外部APIへ接続できずにタイムアウトし、期待したログが出る前に終了するケースはあります。
8. C# Lambdaを実務で使いやすくする設計のポイント
8-1. DI・設定ファイル・環境変数の使い分け
C#の実務開発では、DIを使って依存関係を管理することが多いです。LambdaでもDIは利用できますが、初期化コストを意識する必要があります。
基本的な考え方は次のとおりです。
| 要素 | 使い方 |
|---|---|
| DI | サービス、リポジトリ、クライアントの依存関係を管理 |
| 環境変数 | 環境ごとに変わる設定値を管理 |
| 設定ファイル | ローカル開発や共通設定に利用 |
| Secrets Manager | 機密情報を安全に管理 |
DIコンテナは、関数呼び出しのたびに作るのではなく、できるだけコンストラクタや静的フィールドで初期化し、再利用できる構成にします。
C#public class Function
{
private readonly OrderService _orderService;
public Function()
{
var tableName = Environment.GetEnvironmentVariable("TABLE_NAME")
?? throw new InvalidOperationException("TABLE_NAME is not set.");
_orderService = new OrderService(tableName);
}
public async Task<string> FunctionHandler(OrderRequest request, ILambdaContext context)
{
await _orderService.ProcessAsync(request);
return "OK";
}
}
Lambdaの実行環境は再利用されることがあるため、重い初期化処理を毎回Handler内で実行しないようにすることがポイントです。
8-2. AWS SDK for .NETを使ってS3やDynamoDBと連携する
C# LambdaからAWSサービスを操作する場合は、AWS SDK for .NETを使います。
S3へアクセスする例です。
C#using Amazon.S3;
using Amazon.S3.Model;
public class Function
{
private static readonly AmazonS3Client S3Client = new();
public async Task<string> FunctionHandler(string key, ILambdaContext context)
{
var bucketName = Environment.GetEnvironmentVariable("BUCKET_NAME")
?? throw new InvalidOperationException("BUCKET_NAME is not set.");
var response = await S3Client.GetObjectAsync(new GetObjectRequest
{
BucketName = bucketName,
Key = key
});
using var reader = new StreamReader(response.ResponseStream);
return await reader.ReadToEndAsync();
}
}
DynamoDBへ書き込む例です。
C#using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
public class OrderRepository
{
private readonly Table _table;
public OrderRepository(string tableName)
{
var client = new AmazonDynamoDBClient();
_table = Table.LoadTable(client, tableName);
}
public Task SaveAsync(string orderId, decimal amount)
{
var document = new Document
{
["OrderId"] = orderId,
["Amount"] = amount
};
return _table.PutItemAsync(document);
}
}
AWS SDKのクライアントは、毎回作るよりも再利用したほうが効率的です。特にHttpClientやAWS SDKクライアントをHandler内で毎回生成すると、パフォーマンスや接続管理の面で不利になることがあります。
8-3. コールドスタートを意識した実装
Lambdaでは、実行環境が新しく起動する初回呼び出し時に、通常より時間がかかることがあります。これをコールドスタートと呼びます。
C# Lambdaでコールドスタートを抑えるには、次の点を意識します。
| 対策 | 内容 |
|---|---|
| 初期化処理を軽くする | コンストラクタで重い処理をしすぎない |
| 不要なライブラリを減らす | パッケージサイズを小さくする |
| メモリを調整する | 処理速度が改善する場合がある |
| クライアントを再利用する | AWS SDKクライアントを静的に保持する |
| Native AOTを検討する | 要件に合えば起動時間短縮に役立つ |
AWS Lambdaでは.NETのNative AOTに関するドキュメントも用意されています。特に起動時間を重視する関数では、通常のマネージド実行だけでなく、AOTの適用可否も検討材料になります。AWS ドキュメント
ただし、AOTはすべてのライブラリやリフレクション利用に向いているわけではありません。初心者はまず通常のZIPデプロイで構築し、必要になった段階でコールドスタート対策を進めるのがおすすめです。
8-4. 例外処理とログ出力のベストプラクティス
C# Lambdaでは、例外処理とログ出力を最初から設計しておくことが重要です。エラーが起きたときに原因を追えるように、入力値、処理ステップ、外部サービス呼び出し結果、例外情報を適切に記録します。
基本的な例です。
C#public async Task<string> FunctionHandler(Request request, ILambdaContext context)
{
try
{
context.Logger.LogInformation($"Start processing. RequestId={context.AwsRequestId}");
await ProcessAsync(request);
context.Logger.LogInformation("Processing completed.");
return "OK";
}
catch (Exception ex)
{
context.Logger.LogError($"Error occurred. Message={ex.Message}, StackTrace={ex.StackTrace}");
throw;
}
}
ただし、ログに出してはいけない情報もあります。
| 出してよい情報 | 出してはいけない情報 |
|---|---|
| リクエストID | パスワード |
| 処理ステータス | アクセストークン |
| エラー種別 | クレジットカード番号 |
| 対象リソース名 | 個人情報の詳細 |
| 処理時間 | 秘密鍵 |
API Gateway経由のLambdaでは、例外をそのまま投げると500エラーになります。ユーザー向けのレスポンスと内部ログを分けることが大切です。
C#return new APIGatewayProxyResponse
{
StatusCode = 500,
Body = "Internal server error."
};
8-5. テストしやすいコード構成にする方法
LambdaのHandlerにすべての処理を書くと、テストしにくくなります。実務では、Handlerは薄くし、業務ロジックを別クラスに分離するのがおすすめです。
悪い例です。
C#public async Task<string> FunctionHandler(Request request, ILambdaContext context)
{
// 入力チェック
// DB接続
// 業務処理
// 外部API呼び出し
// レスポンス作成
// すべてここに書いている
}
改善例です。
C#public class Function
{
private readonly OrderService _service = new();
public async Task<Response> FunctionHandler(Request request, ILambdaContext context)
{
return await _service.ProcessAsync(request);
}
}
業務ロジックをOrderServiceに分けると、Lambdaに依存しない単体テストを書きやすくなります。
C#public class OrderServiceTests
{
[Fact]
public async Task ProcessAsync_ReturnsSuccess()
{
var service = new OrderService();
var result = await service.ProcessAsync(new Request
{
OrderId = "A001"
});
Assert.True(result.Success);
}
}
テストしやすい構成にしておくと、LambdaからECSや通常のWeb APIへ移行する場合にもロジックを再利用しやすくなります。
9. C# Lambdaの料金・運用・セキュリティで確認すべきこと
9-1. Lambdaの料金が発生する仕組み
AWS Lambdaの料金は、主にリクエスト数と実行時間に基づいて発生します。実行時間は、設定したメモリ量と実際の実行時間の組み合わせで計算されます。AWS Lambdaの無料枠には、月100万リクエストと月400,000GB秒のコンピューティング時間が含まれます。Amazon Web Services, Inc.
つまり、短時間で終わる小さな処理であれば低コストで運用しやすい一方、実行回数が非常に多い処理や、長時間実行される処理では料金が増えます。
料金に影響する主な要素は次のとおりです。
| 要素 | 料金への影響 |
|---|---|
| リクエスト数 | 呼び出し回数が多いほど増える |
| 実行時間 | 処理が長いほど増える |
| メモリサイズ | 大きいほど単価に影響する |
| アーキテクチャ | x86_64かarm64か |
| ログ量 | CloudWatch Logsの保存にも注意 |
| 連携サービス | API Gateway、S3、DynamoDBなどの料金も発生する |
Lambda単体だけでなく、周辺サービスを含めたコストを見ることが重要です。
9-2. 無料枠とコストを抑える設定
学習用や小規模なC# Lambdaであれば、無料枠内に収まることもあります。ただし、無限リトライ、想定外の大量アクセス、大量ログ出力などがあると、気づかないうちにコストが増える可能性があります。
コストを抑えるためのポイントは次のとおりです。
| 対策 | 内容 |
|---|---|
| タイムアウトを短めに設定 | 無駄に実行され続けるのを防ぐ |
| ログを出しすぎない | 大量ログによるコスト増を防ぐ |
| 同時実行数を制限 | 下流サービスやコストを守る |
| EventBridgeのスケジュール確認 | 想定以上に頻繁に実行しない |
| リトライ設定確認 | 失敗時に繰り返し実行されすぎないようにする |
| AWS Budgets設定 | 予算超過を通知する |
初心者は、Lambdaを作成したら必ず削除方法も確認しておきましょう。使わなくなった関数、API Gateway、CloudWatch Logs、S3バケット、DynamoDBテーブルなどを放置すると、少額でも料金が発生し続けることがあります。
9-3. IAMロールは最小権限で設定する
Lambdaの実行ロールには、必要最小限の権限だけを付与します。たとえば、特定のS3バケットからファイルを読むだけなら、すべてのS3操作を許可する必要はありません。
避けたい例です。
JSON{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
改善例です。
JSON{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::example-bucket/*"
}
IAM権限は、開発中は広めに付けて後から絞るのではなく、最初から必要な操作を洗い出して設定するのが理想です。どうしても原因切り分けのために一時的に権限を広げる場合は、検証後に必ず戻します。
9-4. シークレット情報をコードに書かない方法
C# Lambdaのコードに、APIキー、DBパスワード、アクセストークンなどを書いてはいけません。
悪い例です。
C#var apiKey = "xxxxxxxxxxxxxxxx";
代わりに、次のような方法で管理します。
| 方法 | 用途 |
|---|---|
| 環境変数 | 機密性が低い設定値 |
| AWS Secrets Manager | APIキー、DBパスワードなど |
| AWS Systems Manager Parameter Store | 設定値や一部の秘密情報 |
| IAMロール | AWSサービスへの認証をキーなしで行う |
AWSサービスへアクセスする場合は、アクセスキーをコードに書くのではなく、Lambda実行ロールを使います。これにより、キーの漏えいリスクを減らせます。
Secrets Managerから値を取得する場合も、取得したシークレットをログに出さないよう注意してください。
9-5. 本番運用前に確認したい監視・アラート設定
本番運用でC# Lambdaを使う場合、デプロイして終わりではありません。エラーが起きたときに気づけるよう、監視とアラートを設定します。
確認すべきメトリクスは次のとおりです。
| メトリクス | 見る理由 |
|---|---|
| Errors | エラー発生数 |
| Duration | 実行時間 |
| Throttles | 同時実行制限による抑制 |
| Invocations | 呼び出し回数 |
| ConcurrentExecutions | 同時実行数 |
| IteratorAge | ストリーム処理の遅延確認 |
| DeadLetterErrors | 失敗イベント処理の確認 |
CloudWatch Alarmを使って、エラー数が一定以上になったら通知するようにします。通知先にはSNS、メール、Slack連携などを使えます。
また、障害時に原因を追えるよう、ログにはリクエストIDや処理対象IDを含めておくと便利です。
10. C#でAWS Lambdaを始めるときのよくある質問
10-1. C#初心者でもAWS Lambdaは使える?
C#初心者でもAWS Lambdaは使えます。ただし、完全なプログラミング初心者がいきなりAWS Lambdaから始めると、C#、.NET、AWS、IAM、JSON、デプロイ、ログ調査を同時に学ぶことになり、難しく感じやすいです。
おすすめの学習順は次のとおりです。
C#の基本文法を学ぶ
クラス、メソッド、async/awaitを理解する
JSONとシリアライズを学ぶ
.NET CLIでビルドとテストを行う
AWS Lambdaでシンプルな関数を動かす
CloudWatch Logsでログを見る
S3やDynamoDBと連携する
最初は「文字列を受け取って大文字にして返す」程度の小さな関数から始めるのがおすすめです。
10-2. .NET 8と.NET 10はどちらを選べばいい?
新規でC# Lambdaを作るなら、基本的には.NET 10を選ぶのがおすすめです。AWS Lambdaは.NET 10をマネージドランタイムとしてサポートしており、AWSは.NET 10を使ったサーバーレスアプリケーションの作成をサポートすると発表しています。Amazon Web Services, Inc.
ただし、次の場合は.NET 8を選ぶ判断もあります。
| 状況 | 選択 |
|---|---|
| 新規開発 | 基本は.NET 10 |
| 既存Lambdaが.NET 8 | まずは.NET 8継続でもよい |
| ライブラリが.NET 10未対応 | .NET 8で安定運用 |
| チームが.NET 8で標準化済み | 移行計画を立ててから.NET 10 |
| 長期運用を見据える | サポート期限を比較して判断 |
重要なのは、AWS Lambda側のランタイム対応、Microsoftのサポート期限、利用ライブラリ、チームの運用体制を合わせて判断することです。
10-3. Visual StudioなしでもC# Lambdaは作れる?
Visual StudioなしでもC# Lambdaは作れます。.NET SDK、AWS CLI、Amazon.Lambda.Toolsがあれば、VS Code、Rider、Vim、Cursorなどのエディタでも開発できます。
基本コマンドは次の流れです。
Bashdotnet new install Amazon.Lambda.Templates
dotnet new lambda.EmptyFunction -n MyCSharpLambda
cd MyCSharpLambda
dotnet test
dotnet lambda deploy-function MyCSharpLambda
Visual Studioは便利ですが、必須ではありません。むしろ実務では、CI/CDで同じコマンドを実行できるように、CLIベースの手順を理解しておくことが重要です。
10-4. LambdaでASP.NET Core Web APIは動かせる?
LambdaでASP.NET Core Web APIを動かすことは可能です。AWS公式ドキュメントでは、Amazon.Lambda.AspNetCoreServer NuGetパッケージを使ってASP.NETアプリケーションをLambdaにデプロイする方法が案内されています。AWS ドキュメント
構成としては、API GatewayとLambdaを組み合わせ、HTTPリクエストをASP.NET Coreアプリケーションに橋渡しします。
クライアント → API Gateway → Lambda上のASP.NET Core Web API
ただし、通常のASP.NET CoreアプリをEC2やECSで常時起動する場合とは実行モデルが違います。コールドスタート、タイムアウト、Lambdaの制限、API Gatewayの仕様を理解したうえで採用しましょう。
小規模なAPIや社内ツール、アクセス頻度が低いAPIには向いています。一方で、常時高トラフィックのWeb APIでは、ECS、EKS、App Runnerなども比較検討するとよいでしょう。
10-5. デプロイ後にコード変更が反映されないときは?
デプロイ後にコード変更が反映されないときは、まず次の順番で確認します。
| 順番 | 確認内容 |
|---|---|
| 1 | 正しいリージョンを見ているか |
| 2 | 正しい関数名へデプロイしたか |
| 3 | dotnet build -c Releaseが成功しているか |
| 4 | dotnet lambda deploy-functionが成功しているか |
| 5 | Lambdaの最終更新日時が変わっているか |
| 6 | API Gatewayが正しいLambdaを呼んでいるか |
| 7 | エイリアスやバージョンが古くないか |
| 8 | クライアント側キャッシュを見ていないか |
特に多いのは、東京リージョンにデプロイしたのに、コンソールでバージニア北部リージョンを見ているケースです。また、API GatewayやLambdaエイリアスを使っている場合、呼び出し元が古いバージョンを参照していることもあります。
10-6. まず何から学べば実務で使えるようになる?
C# Lambdaを実務で使えるようになるには、Lambda単体だけでなく、周辺サービスとの組み合わせを学ぶ必要があります。
おすすめの学習ロードマップは次のとおりです。
| ステップ | 学ぶ内容 |
|---|---|
| 1 | C#の基本、async/await、例外処理 |
| 2 | .NET CLI、NuGet、単体テスト |
| 3 | AWS Lambdaの作成、Handler、デプロイ |
| 4 | CloudWatch Logsでログ調査 |
| 5 | IAMロールと最小権限 |
| 6 | API Gateway + Lambda |
| 7 | S3イベント + Lambda |
| 8 | DynamoDBやSQSとの連携 |
| 9 | 環境変数、Secrets Manager、Parameter Store |
| 10 | CI/CD、監視、アラート、コスト管理 |
最初から完璧なアーキテクチャを目指す必要はありません。まずは小さなC# Lambdaを1つ作り、ログを見ながらAWS上で動く感覚をつかむことが大切です。
まとめ
C#でAWS Lambdaを始めるには、.NET SDK、AWS CLI、Amazon.Lambda.Tools、Lambdaテンプレートを準備し、シンプルなC# Lambda関数を作成するところから始めます。最初は空のLambda関数を作り、dotnet testでテストし、Mock Lambda Test Toolでローカル確認し、dotnet lambda deploy-functionでAWSへデプロイする流れを覚えましょう。
C# Lambdaで特につまずきやすいのは、Handler指定、JSONシリアライズ、IAM権限、タイムアウト、CloudWatch Logsの確認です。エラーが出たときは、まずHandler、ランタイム、実行ロール、環境変数、ログを順番に確認すると原因を切り分けやすくなります。
実務で使う場合は、Handlerにすべてを書かず、業務ロジックを別クラスに分け、DI、環境変数、AWS SDK、ログ出力、例外処理を意識した設計にしましょう。また、IAMロールは最小権限にし、シークレット情報をコードに書かず、CloudWatch Alarmや予算アラートで運用面も整えることが重要です。
C#、Lambda、AWSの3つを一度に学ぶと難しく感じるかもしれません。しかし、小さな関数から始めて、API Gateway、S3、EventBridge、DynamoDBへ少しずつ広げていけば、サーバー管理なしで実用的なクラウド処理を作れるようになります。C#の知識を活かしてAWS Lambdaを使いたい人は、まずシンプルな関数を1つ作成し、ローカルテストからデプロイ、CloudWatch Logsでの確認まで一通り体験してみましょう。

