Ahmad Nabil
Ahmad Nabil

Reputation: 465

Should I close an RDS Proxy connection inside an AWS Lambda function?

I'm using Lambda with RDS Proxy to be able to reuse DB connections to a MySQL database.

Should I close the connection after executing my queries or leave it open for the RDS Proxy to handle?

And if I should close the connection, then what's the point of using an RDS Proxy in the first place?

Here's an example of my lambda function:

const mysql = require("mysql2/promise")

const config = {
  host: process.env.RDS_HOST, // RDS Proxy endpoint here
  user: process.env.RDS_USER,
  database: process.env.RDS_DATABASE,
  password: process.env.RDS_PASSWORD,
  ssl: "Amazon RDS"
}

exports.handler = async (event) => {
  let connection

  try {
    connection = await mysql.createConnection(config)
    console.log(`Connected to db. ConnectionId: ${connection.threadId}`)

    // Do some queries
  } catch (err) {
    return handleError(err)
  } finally {
    if (connection) await connection.end() // Should I close the connection here?
  }

  return response(200, "Success")
}

EDIT: Beware that initializing the connection outside the handler (global scope) will make the lambda function retain the value of the connection variable between invocations in the same execution environment which will result in the following error Can't add new command when connection is in closed state when calling the lambda function multiple times in a short period of time because the connection is already closed in the first invocation, so I'd better suggest defining the connection inside the handler not outside.

Upvotes: 10

Views: 6989

Answers (2)

Daniel Young
Daniel Young

Reputation: 91

There are some considerable differences between connecting directly to RDS, and connecting to the RDS proxy, the most notable of which, is that RDS proxy decouples the client connection, from the database connection. The "client connection" (Lambda => RDS Proxy) is the first leg of the request which is then fulfilled by a "database connection" (RDS Proxy => RDS) which is borrowed from an existing connection pool, maintained by the RDS Proxy. When the transaction is finished, the database connection is returned to the connection pool to be reused. From the docs:

RDS Proxy can reuse a connection after each transaction in your session. This transaction-level reuse is called multiplexing. When RDS Proxy temporarily removes a connection from the connection pool to reuse it, that operation is called borrowing the connection. When it's safe to do so, RDS Proxy returns that connection to the connection pool.

In a traditional architecture, where you are connecting directly to the database, it is typical to maintain the "client connections" locally on the client. As such, in this type of architecture we tend to use the term "connection" to refer to both the client and database connections because we often use simple design patterns that don't include a pool of warm connections to borrow from. In these architectures, it often makes sense to explicitly close connections when we are through with them, particularly with ephemeral runtimes like AWS Lambda which could otherwise lead to hanging connections in unexpected executions.

With RDS Proxy however, we want to cache the "client connection", as it will eliminate the setup overhead required to establish authorization to the RDS instance. Because it decouples client connections from db connections, RDS Proxy can handle a much larger number of client connections than database connections.

To break it down:

  • When you initialize a connection, you are only establishing a "client connection" with RDS Proxy
  • If you use that connection to run a query, RDS Proxy will borrow a "database connection" to perform your query
  • Once the query completes (or in the case of an interruption, the borrow timeout is reached) the "database connection" is returned to the pool

This is ultimately the whole point of RDS Proxy. I would recommend keeping your connection in global state, and not closing the connection at the end of the lambda invocation. This will allow you to maintain the performance benefit of caching the client connection to RDS Proxy.

Upvotes: 0

Ermiya Eskandary
Ermiya Eskandary

Reputation: 23682

TDLR: always close database connections

The RDS proxy sits between your application and the database & should not result in any application change other than using the proxy endpoint.


Should I close the connection after executing my queries or leave it open for the RDS Proxy to handle?

You should not leave database connections open regardless of if you use or don't use a database proxy.

Connections are a limited and relatively expensive resource.

The rule of thumb is to open connections as late as possible & close DB connections as soon as possible. Connections that are not explicitly closed might not be added or returned to the pool. Closing database connections is being a good database client.

Keep DB resources tied up with many open connections & you'll find yourself needing more vCPUs for your DB instance which then results in a higher RDS proxy price tag.


And if I should close the connection, then what's the point of using an RDS Proxy in the first place?

The point is that your Amazon RDS Proxy instance maintains a pool of established connections to your RDS database instances for you - it sits between your application and your RDS database.

The proxy is not responsible for closing local connections that you make nor should it be.

It is responsible for helping by managing connection multiplexing/pooling & sharing automatically for applications that need it.

An example of an application that needs it is clearly mentioned in the AWS docs:

Many applications, including those built on modern serverless architectures, can have a large number of open connections to the database server, and may open and close database connections at a high rate, exhausting database memory and compute resources.


To prevent any doubt, also feel free to check out an AWS-provided example that closes connections here (linked to from docs), or another one in the AWS Compute Blog here.

Upvotes: 10

Related Questions