Using a database
AWS offers the RDS service to run MySQL and PostgreSQL databases.
Here are some of the database services offered by RDS:
- Aurora MySQL/PostgreSQL: closed-source database with MySQL/PostgreSQL compatibility
- Aurora Serverless MySQL/PostgreSQL: similar to Aurora but scales automatically on-demand
Aurora Serverless 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.
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)
Note that Aurora Serverless cannot be made publicly accessible, 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 you use Aurora Serverless, you can also use the RDS Data API. SQL queries are executed through an HTTP API instead of the traditional MySQL/PostgreSQL connection. To help you, the dbal-rds-data library is a Doctrine DBAL driver. Please note that the library and the API itself are new and experimental.
Accessing the internet
⚠️ WARNING ⚠️
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 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 will need to create a NAT Gateway in the VPC: you can follow this tutorial, use the serverless VPC plugin, or use the complete example in Serverless Visually Explained.
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.
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.
Creating a database
On the RDS console:
- 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
Accessing the database from PHP
It may take some 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 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 (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):
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/):
- 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.
Accessing the database from your machine
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, made by Bref maintainers:
To expose the database publicly on the internet, follow this guide.