'Adding a DBContext to AWS Lambda causes it to hang

I am new to C# and Serverless development. I am trying to create an AWS Lambda that has an API Gateway trigger. When the Lambda triggers I want to write a User record to the database.

Lambda:

namespace CreateProfile;

using System.Net;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;

using Database;
using Users.Models;

public class Function
{
    /// <summary>
    /// This Lambda function is for creating a user profile
    /// </summary>
    public APIGatewayHttpApiV2ProxyResponse FunctionHandler(User user, ILambdaContext context)
    {
        LambdaLogger.Log($"Calling function name: {context.FunctionName}\n");
        LambdaLogger.Log($"Payload Received: {user}");
        
        // 1. Populate the relevant table(s) from our input
        using myDbContext ctx = new();
        ctx.Users.Add(user);
        ctx.SaveChanges();
        
        APIGatewayHttpApiV2ProxyResponse response = new ()
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = "Great Scott...it worked!",
            Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } }
        };
        return response;
    }
}

I am using the following Assembly:

using Amazon.Lambda.Core;
using Amazon.Lambda.Serialization.SystemTextJson;


// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(
    DefaultLambdaJsonSerializer
))]

I am using the following as my database context:

namespace Database;

using Users.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using Npgsql;

[DbConfigurationType(typeof(Config))]
public class MyDbContext: DbContext
{
    public myDbContext(): base(MakeConnString()) {}

    private static string MakeConnString()
    {
        // Will be moving these to a common location
        string OptEnv(string key, string default_) =>
            Environment.GetEnvironmentVariable(key) ?? default_;

        string Env(string key) =>
            Environment.GetEnvironmentVariable(key) ?? throw new MissingFieldException(key);

        NpgsqlConnectionStringBuilder builder = new()
        {
            Host = Env("PGHOST"),
            Port = int.Parse(OptEnv("PGPORT", "5432")),
            SslMode = Enum.Parse<SslMode>(OptEnv("PGSSLMODE", "Require")),
            TrustServerCertificate = true,
            Database = OptEnv("PGDATABASE", "postgres"),
            Username = OptEnv("PGUSER", "postgres"),
            Password = Env("PGPASSWORD")
        };
        return builder.ConnectionString;
    }
    public DbSet<User> Users { get; set; }
}

When running this my Lambda hangs and I can't figure out why.



Solution 1:[1]

I'm assuming the database you are trying to interact with is an RDS instance or running on an EC2 instance in the same account, right?

If so, are your Lambda function deployed into your VPC? If not, the Lambda needs to be in order to talk to a VPC resource. The default is the Lambdas are NOT deployed in your VPC.

If you are using Serverless Framework then you need to add the following config to the provider section of your serverless.yml [https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml]

provider:
  # Optional VPC settings
  # If you use VPC then both securityGroupIds and subnetIds are required
  vpc:
    securityGroupIds:
      - securityGroupId1
    subnetIds:
      - subnetId1
      - subnetId2

The subnets you reference need to have a route to the subnets your database is provisioned into. They can be in the same subnets as the ones your RDS instance or EC2 is running the in DB.

Lastly, you need to ensure that the Security Group allows outbound traffic on the correct port for your Lambda Security Group, as well as, ensure that the Security Group on your database (EC2 or RDS) allows traffic from either the Lambda SG or the CIDR/IP ranges of the subnets you are deploying the Lambdas into on the correct port #.

The hanging is typically the request not making it to the DB - if you are already set up with your Lambda deployed in your VPC, then you should check the routing and Security Groups mentioned.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1