Serverless Function Best Practices

On this page Carat arrow pointing down
Warning:
Cockroach Labs will stop providing Assistance Support for v21.2 on May 16, 2023. Prior to that date, upgrade to a more recent version to continue receiving support. For more details, see the Release Support Policy.

This page provides best practices for optimizing the performance of serverless functions (e.g., AWS Lambda functions and Google Cloud Functions) that connect to CockroachDB.

Use connection pools

Use connection pools to manage the lifecycle of database connections established by serverless functions. Connection pools health-check connections and re-establish broken connections in the event of a communication error.

When creating connection pools in serverless functions:

  • Set the maximum connection pool size to 1, unless your function is multi-threaded and establishes multiple concurrent requests to your database within a single function instance.

  • Do not set a minimum idle connection count. The connection pool should be free to open connections as needed.

  • If supported by your pooling library, set the maximum lifetime on the connection pool to 30 minutes.

Persist connection pools across function invocations

If you plan to invoke a serverless function at a high frequency, you should configure the function to persist connection pools across function invocations, to limit the number of new connection attempts to the database. This is typically done by initializing the connection pool variable outside the scope of the serverless function definition.

For example, suppose you are writing an AWS Lambda function that INSERTs data into a table on a CockroachDB cluster, and you plan to run this query every few seconds. To persist a connection pool across invocations, initialize the connection pool variable outside of the handler function definition and then define the connection pool in the handler only if the pool does not already exist.

A node.JS function that implements this pattern could look similar to the following:

icon/buttons/copy
const { Pool } = require('pg')

let pool

const insertRows = async (p) => {
  const client = await p.connect()
  try {
    await client.query('INSERT INTO table (col1, col2) VALUES (val1, val2)')
  } catch (err) {
    console.log(err.stack)
  } finally {
    client.release()
  }
}

exports.handler = async (context) => {
  if (!pool) {
    const connectionString = process.env.DATABASE_URL
    pool = new Pool({
      connectionString,
      max: 1
    })
  }

  await insertRows(pool)
}

A Python function that implements this pattern could look similar to the following:

icon/buttons/copy
from psycopg2.pool import SimpleConnectionPool

pool = None


def query(p):
  conn = p.getconn()
  with conn.cursor() as cur:
      cur.execute("INSERT INTO table (col1, col2) VALUES (val1, val2)")
      conn.commit()

def lambda_handler(context):
    global pool

    if not pool:
        pool = SimpleConnectionPool(0, 1, dsn=os.environ['DATABASE_URL'])

    query(pool)

    return

Use CockroachDB serverless

As a database-as-a-service, CockroachDB serverless abstracts away the complexity of deploying, scaling, and load-balancing your database. Additionally, idle database connections to CockroachDB use very little memory (~20-30 KiB) when compared to PostgreSQL (~2-10 MiB).

To create a free CockroachDB serverless cluster:

  1. If you haven't already, sign up for a CockroachDB Cloud account.
  2. Log in to your CockroachDB Cloud account.
  3. On the Clusters page, click Create Cluster.
  4. On the Create your cluster page, select Serverless.

    Unless you change your monthly budget, this cluster will be free forever.

  5. Click Create cluster.

    Your cluster will be created in a few seconds and the Create SQL user dialog will display.

Deploy serverless functions in the same region as your database

To minimize network latency, you should deploy your serverless functions in the same region as your database deployment. If your serverless function provider does not offer deployments in the same region as your database deployment, choose the region closest to the region where your database is deployed.

See also


Yes No
On this page

Yes No