The evolution of Serverless Postgres
Tags: postgres, serverless, neon, aws
Published: 2024-05-30 16:21:07

Among the many options available for running managed Postgres, Amazon Aurora Serverless initially stood out as unique when it was announced. It promised to introduce the concepts of scaling to zero, autoscaling, and usage-based pricing to Postgres. 

A lot has changed since then,[ including AWS's decision to deprecate scale-to-zero in Aurora. ](https://www.reddit.com/r/aws/comments/18sx0i6/aurora_serverless_v1_eol_december_31_2024/)Today, developers have other options for running serverless Postgres, such as [Neon](https://neon.tech). In this comparison, we'll examine the key differences between Aurora and Neon, focusing on their serverless capabilities and pricing models.


### Navigating the Amazon Aurora universe 

Let’s start by clarifying terminology. When developers refer to “Amazon Aurora”, they might be referring to _three_ different products: 



* **[Amazon Aurora provisioned](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/User_DBInstanceBilling.html)** is the “traditional” version of Amazon Aurora, where you provision database instances with a fixed capacity. You have to specify the instance size upfront, and you are billed based on the allocated resources regardless of usage.
* **[Amazon Aurora Serverless v1](https://aws.amazon.com/rds/aurora/serverless/)** came next as the first serverless version of Amazon Aurora. The two core functionalities it introduced were scale to zero and autoscaling: Aurora Serverless v1 instances automatically start up, shut down, and scale capacity up or down based on your application's needs. It's positioned as a more optimal choice for applications with intermittent, unpredictable, or variable workloads. 
* **[Amazon Aurora Serverless v2](https://aws.amazon.com/rds/aurora/serverless/)** aimed to address the limitations of v1. It claimed to offer more fine-grained scaling, improved performance, and the same high availability and durability as the provisioned instances. But these improvements came at a high price: **losing scale to zero. **

In Aurora Serverless v1, if there were no database connections or activity for a period of time, the database could automatically pause and reduce capacity to zero, effectively eliminating costs during idle periods. This capability was essential to the claim of serverless as a way to reduce costs for applications with “infrequent usage patterns” running in Aurora. 

In contrast, Aurora Serverless v2 maintains a minimum capacity of 0.5 ACUs (Aurora Capacity Units) even when there is no database activity. As we’ll explore later in the post, this means that there are always some costs incurred, regardless of usage. This approach was taken to ensure instant provisioning and [to eliminate the latency associated with cold starts](https://neon.tech/blog/aurora-serverless-v1-to-neon#:~:text=Faster%20cold%20starts%20%E2%80%93%20500ms%20P95%20start%20time%20on%20Neon%2C%20vs%2020%2D60s%20on%20V1), but it came with a trade-off in costs for users. 


### Now, meet Neon

[Neon's architecture](https://neon.tech/blog/architecture-decisions-in-neon) is inspired by Amazon Aurora and its separation of compute and storage. But Neon takes this design one step further by adopting [a custom-built storage engine that keeps a history](https://neon.tech/blog/what-you-get-when-you-think-of-postgres-storage-as-a-transaction-journal) of Postgres transactions. This enables Neon not only to offer a truly serverless experience with scale to zero, but also to focus on [improving development workflows by offering features like database branching](https://neon.tech/flow). 

Neon [automatically scales compute instances to zero](https://neon.tech/docs/introduction/auto-suspend) when inactive for a specified period (5 minutes by default). Similar to Aurora Serverless, it includes [autoscaling](https://neon.tech/docs/introduction/autoscaling) to dynamically adjust compute resources based on the current load within user-defined limits. Differently to Aurora, Neon comes with a free tier. 


### Features: Neon vs Aurora Serverless v2 

Let’s dig deeper into how Neon compares to Amazon Aurora Serverless in terms of features.  This table gives you the high-level view: 


<table>
  <tr>
   <td><strong>Feature</strong>
   </td>
   <td><strong>Amazon Aurora Serverless v2</strong>
   </td>
   <td><strong>Neon</strong>
   </td>
  </tr>
  <tr>
   <td>Scale-to-zero
   </td>
   <td>No, it maintains a minimum capacity of 0.5 ACU at all times*
   </td>
   <td>Yes, instances can be configured to automatically suspend after a period of inactivity  
   </td>
  </tr>
  <tr>
   <td>Instant provisioning 
   </td>
   <td>No, new instances take up to 20 minutes 
   </td>
   <td>Yes, rapid provisioning of new instances (&lt;500ms)
   </td>
  </tr>
  <tr>
   <td>Compute autoscaling
   </td>
   <td>Yes, by 0.5 ACU increments 
   </td>
   <td>Yes, based on real-time load 
   </td>
  </tr>
  <tr>
   <td>On-demand storage 
   </td>
   <td>Yes, by 10 GB increments 
   </td>
   <td>Yes, by 2-10 GB increments depending on plan
   </td>
  </tr>
  <tr>
   <td>Database branching
   </td>
   <td>No
   </td>
   <td>Yes, with data and schema via copy-on-write 
   </td>
  </tr>
  <tr>
   <td>Multi-AZ replicas
   </td>
   <td>Yes
   </td>
   <td>No, under development 
   </td>
  </tr>
  <tr>
   <td>Read replicas 
   </td>
   <td>Yes, using separate instances  
   </td>
   <td>Yes, without storage redundancy (compute-only)
   </td>
  </tr>
  <tr>
   <td>Point-in-time recovery
   </td>
   <td>Yes, via backups and transaction logs (takes from minutes to hours)
   </td>
   <td>Yes, via database branching (instant)
   </td>
  </tr>
  <tr>
   <td>API support 
   </td>
   <td>Yes, via RDS API 
   </td>
   <td>Yes, via Neon API 
   </td>
  </tr>
  <tr>
   <td>CLI support 
   </td>
   <td>Yes, via AWS CLI
   </td>
   <td>Yes, via Neon CLI 
   </td>
  </tr>
  <tr>
   <td>Postgres extensions 
   </td>
   <td>Limited 
   </td>
   <td>Extensive (200+)
   </td>
  </tr>
  <tr>
   <td>Custom extensions
   </td>
   <td>Not supported  
   </td>
   <td>Supports custom extensions 
   </td>
  </tr>
  <tr>
   <td>Connection pooling 
   </td>
   <td>Yes, using RDS Proxy (for a fee) 
   </td>
   <td>Yes, integrated within Neon’s architecture 
   </td>
  </tr>
  <tr>
   <td>IP Allowlist 
   </td>
   <td>Yes, via security groups
   </td>
   <td>Yes, via customizable access control 
   </td>
  </tr>
  <tr>
   <td>Organization accounts
   </td>
   <td>Yes, via AWS IAM and AWS Organizations 
   </td>
   <td>Yes, natively supported 
   </td>
  </tr>
  <tr>
   <td>Integrations 
   </td>
   <td>Limited outside AWS ecosystem 
   </td>
   <td>Yes, for CI/CD workflows 
   </td>
  </tr>
  <tr>
   <td>Support 
   </td>
   <td>Yes, at extra cost 
   </td>
   <td>Yes, included with plan 
   </td>
  </tr>
  <tr>
   <td>Free tier
   </td>
   <td>No
   </td>
   <td>Yes 
   </td>
  </tr>
</table>


_*If you’re wondering what the heck is an ACU, see the next section._


### Pricing model: Aurora Serverless 

When it’s time to evaluate pricing for Aurora Serverless, you’ll very quickly be confronted with what seems like an easy question to answer: **what is an ACU?**


![Unsolved Mysteries: What are ACUs?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ohdwe7jjwkb6js03njl.png)


Let’s backtrack. In Aurora Serverless, ACUs (Aurora Capacity Units) are the units of measure used to define the capacity of database instances. When running an instance as a user, you’ll define a minimum and maximum ACU limit. Aurora will scale up and down automatically between these minimum and maximum limits, in 0.5 ACU increments.

The minimum number of ACUs varies between Aurora Serverless v1 and v2:



* In Aurora Serverless v1, you can define 0 as the minimum limit (v1 scales to zero).
* In Aurora Serverless v2, the minimum possible limit is 0.5 ACU. We’ll break down what this implies cost-wise in the next section.

Now, to size an Aurora Serverless instance, the first thing you would like to know is how much CPU and memory is contained in each ACU. You will be billed according to how many ACUs you have used in a month, so this is highly relevant: for example, you may suspect that 1 CPU would be enough to handle your peak load, and therefore you would like to set up your maximum ACU limit at a corresponding capacity.

Unfortunately, AWS is opaque in disclosing this information, making pricing in Aurora very uncertain. [According to the Aurora docs](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.how-it-works.html), an ACU is “a combination of approximately 2 gibibytes (GiB) of memory, corresponding CPU, and networking”.

We’re as confused as you are about what this means. [Some folks online have experimented with this](https://www.reddit.com/r/aws/comments/uswz6h/aurora_serverless_v2_in_production/) and concluded that probably 1 ACU = 0.25 vCPU, 2 GiB memory. But we can’t know for sure.

ACU mysteries aside, your monthly Aurora Serverless bill will be calculated as the sum of a few elements, included below. If you avoid the I/O charges by using I/O optimized storage (highly recommended), compute and database storage will most likely be the main elements contributing to your monthly costs.


<table>
  <tr>
   <td><strong>Billing component in Aurora Serverless</strong>
   </td>
   <td><strong>Description  </strong>
   </td>
  </tr>
  <tr>
   <td>Compute 
   </td>
   <td>Billed per ACU-hour based on the capacity used, with a minimum of 0.5 ACU. 
   </td>
  </tr>
  <tr>
   <td>Database storage 
   </td>
   <td>Billed per GB-month in 10 GB increments with a <a href="https://aws.amazon.com/rds/aurora/faqs/#:~:text=The%20minimum%20storage%20is%2010,no%20impact%20to%20database%20performance.">minimum of 10 GB</a>.  
   </td>
  </tr>
  <tr>
   <td>I/O requests 
   </td>
   <td>Only applicable to standard storage (<a href="https://aws.amazon.com/rds/aurora/pricing/">included for I/O optimized</a>).  Billed per million requests. 
   </td>
  </tr>
  <tr>
   <td>Backup storage 
   </td>
   <td>Automated backups up to the size of your database are free. Additional backup storage is billed per GB-month.
   </td>
  </tr>
  <tr>
   <td>Data transfer costs 
   </td>
   <td>Data transfer within the same AWS region is free. Cross-region and outbound data transfer is billed per GB.
   </td>
  </tr>
  <tr>
   <td>Multi-AZ deployments 
   </td>
   <td>Additional costs for the resources used in the additional AZ. 
   </td>
  </tr>
  <tr>
   <td>Read replicas 
   </td>
   <td>Billed for ACU usage, storage, and I/O operations for each read replica. Cross-region replication incurs additional data transfer charges.
   </td>
  </tr>
  <tr>
   <td>Backtrack 
   </td>
   <td>When you “rewind” an Aurora database without restoring from backup. Billed per GB-month for the change records stored.
   </td>
  </tr>
  <tr>
   <td>API 
   </td>
   <td>Charges for using certain APIs provided by Aurora. Billed per million API requests.
   </td>
  </tr>
  <tr>
   <td>Snapshot or cluster export 
   </td>
   <td>Charges for exporting snapshots or clusters to S3. Billed per GB of snapshot or cluster exported.
   </td>
  </tr>
</table>


Since Aurora Serverless v2 doesn’t have a free tier and has minimum requirements for both compute and storage, we can estimate the minimum costs for the smallest database possible running 24/7: 



* [Minimum monthly cost: $65.65 USD.](https://calculator.aws/#/createCalculator/AuroraPostgreSQL)

This is the absolute monthly minimum for a database running in us-east-1, assuming we’re using I/O optimized storage to avoid extra I/O charges.

This calculation assumes that you’re using 0.5 ACU (the minimum) at all times. However, an important practical consideration is that in reality, you’ll be forced to pick an ACU range, and the [lowest maximum ACU possible is 1 ACU](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2-administration.html). So, a better expectation is that, in the previous example, costs would oscillate between $60 and $120 USD approximately.


### Pricing model: Neon

Compute in Neon [with autoscaling enabled](https://neon.tech/docs/introduction/autoscaling) works similarly to Aurora Serverless, but without the opacity. In Neon, 1 CU = 1 vCPU and 4 GiB of memory. You’ll be able to set up minimum and maximum autoscaling limits (with the minimum being able to scale to zero if you wish), and your compute consumption will be billed in CU-hours at the end of the month.

In terms of billing components, Neon offers three [different pricing plans](https://neon.tech/pricing). Your monthly bill will account for:



* The monthly fee corresponding to each plan ($0, $19, or $69)
* Any additional compute or storage usage over what is included within each plan
* Charges per additional projects (the logical equivalent of an instance in Neon)

<table>
  <tr>
   <td>
<strong>Billing component in Neon</strong>
   </td>
   <td><strong>Free</strong>
   </td>
   <td><strong>Launch</strong>
   </td>
   <td><strong>Scale</strong>
   </td>
  </tr>
  <tr>
   <td>Monthly fee
   </td>
   <td>0 \

   </td>
   <td>19 USD
   </td>
   <td>69 USD 
   </td>
  </tr>
  <tr>
   <td>Additional compute usage
   </td>
   <td>N/A - Includes capacity for 24/7 usage with 0.5 CU 
   </td>
   <td>300 CU-hours included with monthly fee. Additional charges after that. 
   </td>
   <td>750 CU-hours included with monthly fee. Additional charges after that. 
   </td>
  </tr>
  <tr>
   <td>Additional storage
   </td>
   <td>N/A - Includes 0.5 GB 
   </td>
   <td>10 GB included with monthly fee. Additional charges after that. 
   </td>
   <td>50 GB included with monthly fee. Additional charges after that. 
   </td>
  </tr>
  <tr>
   <td>Additional projects 
   </td>
   <td>N/A - Includes 1 project 
   </td>
   <td>10 projects included with monthly fee. Additional charges after that. 
   </td>
   <td>50 projects included with monthly fee. Additional charges after that. 
   </td>
  </tr>
</table>



### Comparing compute costs: Neon vs Aurora Serverless v2 

Estimating compute costs is often the hardest piece with serverless databases. To bring some clarity to this, let’s work through some example workloads that teams might see for serverless applications.

For this exercise, we’ll use the following equivalence: 



* 1 ACU in Aurora = 0.5 CU in Neon = 0.5 vCPU, 2 GiB memory.

Taking into consideration that AWS discloses that 1 ACU equals 2 GiB of memory, and that 1 CU in Neon equals 4 GiB of memory, this equivalence seems like a fair assumption—but note that this is approximate. We have reasons to believe that ACUs are even smaller than that CPU-wise, so your** real workload may require higher ACU limits** (and therefore higher costs) than estimated here.


<table>
  <tr>
   <td><strong>Example workload </strong>
   </td>
   <td><strong>Compute costs in Neon</strong>
   </td>
   <td><strong>Compute costs in Aurora Serverless v2</strong>
   </td>
  </tr>
  <tr>
   <td>Low compute (testing) 
   </td>
   <td>41 USD 
   </td>
   <td>701 USD 
   </td>
  </tr>
  <tr>
   <td>Medium compute (analytics) 
   </td>
   <td>69 USD 
   </td>
   <td>467 USD 
   </td>
  </tr>
  <tr>
   <td>High compute (application) 
   </td>
   <td>1,059 USD 
   </td>
   <td>4,064 USD 
   </td>
  </tr>
</table>



#### Low compute, testing workloads

Imagine a small team working on a new feature. They need multiple dev, staging, and testing environments, but each environment has minimal traffic and data storage needs. These databases are often idle for extended periods and only need to be active during specific testing windows. 

Using [database branches](https://neon.tech/docs/introduction/branching), we could do this on the Neon free tier. But, if this workload requires multiple projects, we cand use the Launch tier instead. Let’s say we’re using 1 vCPU (1 CU) for each of our three projects (dev, staging, and testing), but overall, they are idle 80% of the time. So, this becomes:



* 1 CU * 3 Projects * 730 * 0.2 = 438 CU-hours

This is over the 300 compute hours included in the Launch tier, so we’ll also have to pay $0.16 per extra compute hour: 



* $19 + (138 compute hours * $0.16) = $41.08

So, just over $40 monthly for this testing workload with Neon. For Aurora Serverless v2, it is:



* 2 ACU * 3 instances * 730 = 4,380 ACU-hours

**This costs us many more compute hours because we have no scale to zero**. Now, using the standard configuration pricing of $0.16 per ACU-hour in I/O optimized instances:



* 4,380 ACU-hours * $0.16 = $700.8

The Aurora compute cost would be 17x more than the Neon cost for this sceario, mainly due to Neon’s ability to scale to zero. 


#### Medium compute, analytics workloads

Here, the team might need to batch-run analytics queries and generate reports to gain insights into user behavior and application performance.

Let’s do Neon first. Let’s assume we’re still in the Launch tier, that we’ll use 2 vCPUs (CUs), and 1 project.  Again, these analytics runs aren’t constant—we’ll assume that we’re using them 50% of the time and that they’re idle the rest. With Neon, this looks like:



* 2 CUs * 1 Project * 730 * 0.5 = 730 CU-hours

If we stayed on the Launch tier, we’d have to pay 430 extra compute hours, so the extra cost would be:



* $19 + (430 CU-hours * $0.16) = $448.8

**We can get this cost much lower if we upgraded to the Scale tier, which includes 750 CU-hours within the $69 monthly fee. **

With Aurora Serverless v2, we get:



* 4 ACUs * 1 Instance * 730 = 2,920 ACU-hours

Again, if we assume a I/O-optimized storage [so we’re not abused by I/O costs](https://aws.amazon.com/blogs/database/planning-i-o-in-amazon-aurora/), the monthly price would be:



* 2,920 ACU-hours* $0.16 = $467.2


#### High compute, application workloads

A high compute, application workload will be a production environment with significant traffic and low latency.

Here, we’ll use a variable workload, with 8 vCPUs used during working hours (180 hours / month) and 2 /vCPUs during off-peak hours (550 hours / month). We’ll assume 5 instances/projects. **In this scenario, there is no idle time.**

With the Scale tier on Neon, this works out as:



* (8 CUs *180) + (2 CUs * 550) * 5 Projects = 6,940 CU-hours

We have 750 CU-hours included in the Scale tier, so the cost for this would be:



* $69 + (6,190 * $0.16) = $1,059.4

In Aurora Serverless: 



* (16 ACUs * 180) + (4 ACUs * 550) * 5 Instances = 25,400 ACU-hours 

And the monthly price: 



* 25,400 ACU-hours * $0.16 = $4,064


### Conclusion 

Both Amazon Aurora and Neon offer serverless options to run managed Postgres instances. While Aurora provides robust scalability and a rich set of features, Neon stands out with some advantages, mainly the capacity to scale to zero and a simpler and more transparent pricing structure with a free tier. This makes it a more attractive choice for startups and mid-sized businesses.