Using a database
AWS offers the RDS (opens in a new tab) service to run MySQL and PostgreSQL databases.
Here are some of the database services offered by RDS:
- Aurora MySQL/PostgreSQL (opens in a new tab): closed-source database with MySQL/PostgreSQL compatibility
- Aurora Serverless MySQL/PostgreSQL (opens in a new tab): similar to Aurora but scales automatically on-demand
Aurora Serverless v1 can be configured to scale down to 0 instances when unused (which costs $0), however be careful with this option: the database can take up to 30 seconds to un-pause. Aurora Serverless v2 cannot scale down to 0 instances.
All RDS databases can be setup with Lambda in two ways:
- the database can be made publicly accessible and protected by a username and password
- the database can be made inaccessible from internet by putting it in a private network (aka VPC (opens in a new tab))
Aurora Serverless cannot be made publicly accessible (opens in a new tab), only the second option is possible.
While the first solution is simpler, the second is more secure. Using a VPC also comes with a few limitations that are detailed below.
This page documents how to create databases using VPC (the reliable and secure solution). If you want to skip using a VPC you can read the instructions in the "Accessing the database from your machine" section.
If your Lambda function has timeouts, please read this section.
If you plan on using a database, please read this section.
A database inside a VPC (opens in a new tab) is isolated from the internet. Lambda must run in the VPC to access the database, but it will lose access the internet (for example external APIs, and other AWS services).
To be clear:
Lambda will lose internet access in a VPC.
Because of that, you may see errors like this:
Task timed out after 28 seconds
To restore internet access for a lambda you need to create a NAT Gateway in the VPC. This cannot be solved via security group or subnet configuration, only a NAT Gateway can solve this. You can follow this tutorial (opens in a new tab), use the serverless VPC plugin (opens in a new tab), or use the complete example in Serverless Visually Explained (opens in a new tab).
Watch out, a NAT Gateway will increase costs (starts at $27 per month). Note that you can use one VPC and one NAT Gateway for multiple projects. To reduce costs, you can also use a NAT instance (opens in a new tab) (starts at $3 per month).
When possible, an alternative to NAT Gateways is to split the work done by a lambda in 2 lambdas: one in the VPC that accesses the database and one outside that accesses the external API. But that's often hard to implement in practice.
Finally, another free alternative to NAT Gateway is to access AWS services by creating "private VPC endpoints": this is possible for S3, API Gateway, and more (opens in a new tab).
In the RDS console (opens in a new tab):
- click "Create database"
- select the type of database you want to create and fill in the form
- for a simpler configuration leave the default VPC in the last step
Tips to better control costs:
- for non-critical databases you can disable replication
- switch storage to "General Purpose (SSD)" for lower costs
- you can disable "enhanced monitoring" to avoid the associated costs
It may take a few minutes for the database to be created.
The "endpoint", which is the hostname of the database (this information is available only after the database creation has completed)
ℹ️ Instead of connecting via a socket, via
localhostor an IP address, PHP will connect to MySQL via this hostname.
The "security group ID" (in the "VPC security groups" section), which looks like
ℹ️ A security group (opens in a new tab) is a firewall that restricts access to/from the VPC using "Inbound rules" and "Outbound rules".
The list of "subnets", which look like
subnet-12f4130e(there are several subnets)
ℹ️ An AWS region is divided in availability zones (opens in a new tab) (different data centers): there is usually one subnet per availability zone.
Put these information in
serverless.yml in your function configuration (read more about this in the Serverless documentation (opens in a new tab)):
functions: hello: # ... vpc: securityGroupIds: - sg-03f68e1100481622b subnetIds: - subnet-12f4130e - subnet-c5fe33e5 - subnet-11aa85dc - subnet-85dcf240
Now we need to authorize connections to the RDS security group (because the lambda is in the VPC but outside of this VPC group) (https://www.reddit.com/r/aws/comments/8nr8ek/lambda_rds_connection_timeout/ (opens in a new tab)):
- open the database configuration in RDS and click the security group
- in the "Inbound" tab click "Edit"
- add a rule: select MySQL/Aurora (or PostgreSQL) and set a "custom" source: select the security group itself (type
sg-and use the autocompletion)
Your PHP application will be able to connect to the database through the "endpoint" you noted above.
For example a PDO connection string could be:
To learn how to properly store this connection string in your configuration head over to the "Secrets" section of the Variables documentation.
Also refer to the Extensions section to see if you need to enable any database-specific extensions.
You can learn more about limitations and guidelines from the AWS documentation about Configuring a lambda to access resources in a VPC (opens in a new tab).
A database in a VPC cannot be accessed from the outside, i.e. the internet. You cannot connect to it via tools like MySQL Workbench.
Here are some solutions:
- run tasks on Lambda, for example to import a SQL dump, to debug some data…
- insecure: connect from your computer by exposing the database on the internet
- secure: connect from your computer via a SSH tunnel
To create an SSH tunnel easily and securely, check out 7777 (opens in a new tab), made by Bref maintainers:
To expose the database publicly on the internet, follow this guide.