Skip to main content

PostgreSQL utility library for AWS Lambda

Project description

Soong - PostgreSQL utility library for AWS Lambda

The purpose of this library is to let Lambda functions connect to PostgreSQL on RDS and run queries against it.

⚠️ Soong is currently in active development and should be considered work in progress. Do not use in production! ⚠️

How working with a relational DB on Lambda is different

  1. Authentication
  2. Connection Reuse
  3. Resource Constraints

Authentication

Non-Secret Parameters

Database connection parameters, such as the host, port, database name and user name, should be passed to your lambda functions using environment variables. Soong supports this pattern by automatically detecting those variables.

If you are using SAM, you can assign those parameters to all of your functions in the global section of the template, as shown below. Soong will pick these variables automatically.

Globals:
  Function:
    Environment:
      Variables:
        PG_HOST: "postgres1.abcde123.us-east-1.rds.amazonaws.com"
        PG_DBNAME: database1
        PG_USER: jane_doe

Password

A database password however, should not be used at all! Instead, use IAM authentication, as explained in the RDS user guide.

Soong supports this authentication pattern by automatically generating an auth token when running in the Lambda environment.

In order to enable this pattern, you must:

  1. Enable IAM db authentication for your RDS instance (user guide).
  2. Create a database user that uses IAM authentication (user guide). You can also GRANT rds_iam to an existing user.
  3. Create an IAM policy for IAM database access (user guide). Make sure that the policy covers the user from the previous step.
  4. Assign that policy to the role under which your functions execute (user guide).

Finally, you must use RDS API to generate an auth-token to use in place of a password. Soong does that for you behind the scenes whenever you create a connection.

Code Example

If you did all of the above, connecting to the database from your code is now a breeze:

import soong
# The fancy cursor_factory is optional
with soong.connect(cursor_factory=psycopg2.extras.NamedTupleCursor) as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT 'Hello, world!' AS hello;")
        assert cursor.fetchone().hello == 'Hello, world!'

Connection Reuse

In server-full applications, it is a best practice to manage a connection pool that lets various modules in the application reuse database connections. When you decompose an application into serverless-style functions, there is usually no point in a connection pool, because every function most likely needs just one connection. This is why Soong makes it simple to connect, but does not provide a connection pool.

This does not mean that there is no connection reuse. Code that runs outside of the handler function gets reused if the container remains warm and is reused by another invocation of the function.

Moreover, Soong provides a global connection and makes it simple to initialize it lazily, and reconnect when it's closed. See the code examples below.

Code Examples

# A global connection object is defined inside the soong package
import soong

def lambda_handler(event, context):
    with soong.connection() as conn:  # Lazy initialization
        # Run some queries inside a transaction
        pass

You can also control the connection yourself, rather than use Soong's. The code example below shows how to generate the connection at the module scope, outside of the handler, so it can be reused:

import soong

conn = soong.connect()

def lambda_handler(event, context):
    with conn:
        # Run some queries inside a transaction
        pass

Note that you can also generate connections inside the handler if you want them to close rather than remain open for reuse. There are some scenarios where this is the better option, such as when your function rarely gets called, so there is no connection reuse in practice, but every invocation keeps a connection hanging for a while, wasting resources on your database server.

Resource Constraints

With Lambda you pay directly for the CPU/Memory and execution time. Therefore it is important to limit resource utilization to the minimum necessary. In addition, code in lambda functions tends to be short and simple.

In my opinion, with most lambda functions it makes sense to avoid ORM tools, such as SQL Alchemy, and opt for a more direct approach that is also more lightweight.

The Soong query and dml modules provide some well-documented utility functions that save you from writing a lot of boilerplate code in the most common database access use cases.

Code Example

import soong

# Get the gizmo with id 42 from the gizmos table
gizmo42 = soong.query.get(soong.connection(cursor_factory=psycopg2.extras.NamedTupleCursor), 'gizmos', 42)
print(f'Got gizmo {gizmo42.name}')

# Now rename it
# Re-uses the global connection object, that's already been initialized with the cursor_factory
soong.dml.update(soong.connection(), 'gizmos', 42, {'name': 'Gizmo42: The Next Generation'})

# Add a new gizmo
id = soong.dml.insert(soong.connection(),
    'gizmos', {'name': 'Best gizmo ever!', 'color': 'Bright red'}, returning='id')

# Run a SELECT
for gizmo in soong.query.select(soong.connection(), 'gizmos', {'color': 'pink'}):
    print(gizmo.name)

# You can also run an arbitrary query, without the boilerplate
for gizmo in soong.query.execute(soong.connection(), 'SELECT * FROM gizmos WHERE color = %s', ('pink', )):
    print(gizmo.name)

Why "Soong"?

The name is a reference to Noonien Soong, the human cyberneticist who created Data, the android character in Star Trek: The Next Generation.

https://memory-alpha.fandom.com/wiki/Noonian_Soong

A hologram of Dr. Soong from around the time of Data's creation

Source: https://memory-alpha.fandom.com/wiki/Noonian_Soong

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

soong-0.6.0.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

soong-0.6.0-py3-none-any.whl (9.9 kB view details)

Uploaded Python 3

File details

Details for the file soong-0.6.0.tar.gz.

File metadata

  • Download URL: soong-0.6.0.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.7.2

File hashes

Hashes for soong-0.6.0.tar.gz
Algorithm Hash digest
SHA256 f1bffe94e34efefc927dd92b0c99176d9986c8c77472600898c5ae1563b96f08
MD5 d8c42b4d5cdb56cb4d19a0eac088d80e
BLAKE2b-256 dca623c859a0190b3a25e1ab904a5d3295f2939a8cadf0f7728fb3dee5616382

See more details on using hashes here.

File details

Details for the file soong-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: soong-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 9.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.7.2

File hashes

Hashes for soong-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 60843863268de690ab14a92bec7628369c2c865aeaf4af8c077dc6571664bf1c
MD5 56ce48e4f064433655ed46df34e37db2
BLAKE2b-256 16d43b2fb6b638a5a5225f8f2c9f78a54f87f5df025d32ea973392586253a84b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page