<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/00fF6RtH4" -->

---
title: Day 29/30 AWS System Design Patterns | daily.dev
description: A scenario-based system design question examines a SaaS platform where 600+ concurrent Lambda functions each hold a persistent connection to an Aurora...
canonical: https://daily.dev/posts/day-29-30-aws-system-design-patterns-00ff6rth4
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Day 29/30 AWS System Design Patterns | daily.dev
og:description: A scenario-based system design question examines a SaaS platform where 600+ concurrent Lambda functions each hold a persistent connection to an Aurora...
og:url: https://daily.dev/posts/day-29-30-aws-system-design-patterns-00ff6rth4
og:image: https://api.daily.dev/og/posts/00fF6RtH4.png
og:image:alt: Day 29/30 AWS System Design Patterns
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Day 29/30 AWS System Design Patterns

**[Joud Awad](https://daily.dev/sources/iac4jsbu0lv8wbsc85fsh)** · [@joudawad](https://daily.dev/joudawad) · 2 min read · 109 upvotes · 16 comments

## Summary

A scenario-based system design question examines a SaaS platform where 600+ concurrent Lambda functions each hold a persistent connection to an Aurora PostgreSQL database, exceeding max_connections and causing rejected connections. Four possible fixes are presented as a multiple-choice quiz: raising max_connections, using RDS Proxy to pool connections, capping Lambda concurrency, or upgrading the instance class. The framing points toward RDS Proxy as the architecturally sound solution, since the others merely delay hitting the ceiling again.

## Content

A SaaS platform runs 600 Lambda functions _(serverless compute, each environment holds one DB connection for its lifetime)_ concurrently at peak, all connecting directly to an Aurora PostgreSQL cluster _(managed relational database, connection count limited by instance memory)_ (db.r6g.4xlarge) in the same VPC. Each Lambda opens a new database connection on cold start and holds it for the lifetime of the execution environment.

Aurora's default `max_connections` for this instance class caps out at approximately 5,000. During a traffic spike, concurrent Lambda executions reach 650. The database starts rejecting connections with: `FATAL: remaining connection slots are reserved for non-replication superuser connections`.

The team's first proposed fix: increase `max_connections` via a custom Aurora parameter group.

Is this the right call?

A) Yes — raising `max_connections` via a parameter group sets a higher ceiling; each Lambda environment holds one persistent connection, so at 650 concurrent executions you need at least 650 slots, and the current limit is the blocker

B) No — use RDS Proxy _(connection pooler, multiplexes thousands of Lambda connections onto a small pool of real DB connections)_; it sits between Lambda and Aurora so the database sees tens of connections instead of hundreds, without changing Aurora's config

C) No — capping Lambda reserved concurrency at 400 keeps you under the limit, but it artificially throttles availability; as the platform scales to 1,000 concurrent executions next quarter, you hit the ceiling again — the connection-per-Lambda model is the architectural problem, not the concurrency level

D) No — a larger instance class (db.r6g.8xlarge) raises the default `max_connections` ceiling because Aurora derives it from instance memory; but each added connection still consumes that memory for connection overhead, and the next scale event hits the new ceiling again

Answer in the comments.

#AWS #Serverless #SystemDesign #BackendEngineering #CloudArchitecture

## Community discussion

Top comments from developers on daily.dev.

**@joudawad** · 7 upvotes

> The answer is B.
>
> RDS Proxy _(connection pooler, multiplexes thousands of Lambda connections onto a small pool of real DB connections)_ sits between Lambda _(serverless compute, each environment holds one DB connection)_ and Aurora _(managed relational database)_ and maintains a small pool of persistent, multiplexed connections to the database. When 650 Lambda functions invoke simultaneously, they all connect to RDS Proxy — not directly to Aurora. RDS Proxy maps those 650 application connections onto a much smaller number of actual database connections, typically 10–50 depending on query...

**@agustinbarrientos** · 3 upvotes

> RDS Proxy gets my vote, with an alarm on backend connection saturation so the pool doesn't hide a growing queue

**@micahnorwoodjordan** · 2 upvotes

> - A = naive
> - C = diagnoses the problem without the fix
> - D = naive
> - B = i've never used RDS proxy but connection pooling is the winner winner chicken dinner

**@mdshafinahmed** · 2 upvotes

> Thank you brother.

**@joudawad** · 2 upvotes

> A — Increasing `max_connections` is not a scaling solution — it is a RAM tradeoff. Aurora allocates memory per connection. Raising the limit consumes more RAM per additional connection, degrading query performance for everyone. More critically, Lambda's ephemeral execution model means every cold start opens a new connection and every scale-out event adds connections. The ceiling gets hit again the next time concurrency grows.

---

Tags: [#aws](https://daily.dev/tags/aws), [#career](https://daily.dev/tags/career), [#database](https://daily.dev/tags/database), [#aws-lambda](https://daily.dev/tags/aws-lambda)

[View this post on daily.dev](https://daily.dev/posts/day-29-30-aws-system-design-patterns-00ff6rth4)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"DiscussionForumPosting","mainEntityOfPage":"https://daily.dev/posts/day-29-30-aws-system-design-patterns-00ff6rth4","headline":"Day 29/30 AWS System Design Patterns","text":"A scenario-based system design question examines a SaaS platform where 600+ concurrent Lambda functions each hold a persistent connection to an Aurora PostgreSQL database, exceeding max_connections and causing rejected connections. Four possible fixes are presented as a multiple-choice quiz: raising max_connections, using RDS Proxy to pool connections, capping Lambda concurrency, or upgrading the instance class. The framing points toward RDS Proxy as the architecturally sound solution, since the others merely delay hitting the ceiling again.","url":"https://daily.dev/posts/day-29-30-aws-system-design-patterns-00ff6rth4","datePublished":"2026-08-29T17:59:09.503Z","dateModified":"2026-08-29T17:59:49.395Z","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0","description":"Principal Solution Architecture ","worksFor":{"@type":"Organization","name":"Metalab","logo":"https://www.google.com/s2/favicons?domain=metalab.com&sz=128"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"EndorseAction"},"userInteractionCount":80110}},"image":"https://media.daily.dev/image/upload/s--bAVapySa--/f_auto/v1788026388/posts/00fF6RtH4?_a=BAMAMicg0","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":109},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":16}],"comment":[{"@type":"Comment","text":"The answer is B.\nRDS Proxy (connection pooler, multiplexes thousands of Lambda connections onto a small pool of real DB connections) sits between Lambda (serverless compute, each environment holds one DB connection) and Aurora (managed relational database) and maintains a small pool of persistent, multiplexed connections to the database. When 650 Lambda functions invoke simultaneously, they all connect to RDS Proxy — not directly to Aurora. RDS Proxy maps those 650 application connections onto a much smaller number of actual database connections, typically 10–50 depending on query patterns and transaction length. Aurora sees a manageable pool. The connection limit error disappears.\nBeyond connection pooling, RDS Proxy gives you two things a parameter group change does not. First, IAM authentication: Lambda functions authenticate using IAM roles rather than storing database credentials in environment variables. Second, automatic failover: during an Aurora failover, RDS Proxy pins connections to the new primary automatically, reducing failover impact from 30–60 seconds to under 10 seconds.","datePublished":"2026-08-29T18:00:34.047Z","dateModified":"2026-08-29T18:03:47.476Z","url":"https://daily.dev/posts/00fF6RtH4#c-Tyatjbt5h","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":7}},{"@type":"Comment","text":"RDS Proxy gets my vote, with an alarm on backend connection saturation so the pool doesn’t hide a growing queue","datePublished":"2026-08-30T12:14:06.755Z","url":"https://daily.dev/posts/00fF6RtH4#c-RDZONMZKI","author":{"@type":"Person","name":"Agustin Barrientos","url":"https://daily.dev/agustinbarrientos","image":"https://media.daily.dev/image/upload/s--5ayxQnqn--/f_auto/v1788281802/avatars/avatar_wQYYVe5Tbj0NJ7C7qPoa8?_a=BAMAMicg0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":3}},{"@type":"Comment","text":"A = naive\nC = diagnoses the problem without the fix\nD = naive\nB = i’ve never used RDS proxy but connection pooling is the winner winner chicken dinner","datePublished":"2026-09-01T06:47:46.933Z","dateModified":"2026-09-01T06:48:22.526Z","url":"https://daily.dev/posts/00fF6RtH4#c-8rV9wIDfC","author":{"@type":"Person","name":"Micah Norwood","url":"https://daily.dev/micahnorwoodjordan","image":"https://media.daily.dev/image/upload/s--F7AsERgm--/f_auto/v1744468090/avatars/avatar_RkUh6L39HXCnFFgzyIq88"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":2}},{"@type":"Comment","text":"Thank you brother.","datePublished":"2026-08-30T01:34:59.071Z","url":"https://daily.dev/posts/00fF6RtH4#c-OYmY4hGAR","author":{"@type":"Person","name":"Md. Shafin Ahmed","url":"https://daily.dev/mdshafinahmed","image":"https://media.daily.dev/image/upload/s---a0uwu1i--/f_auto/v1783046504/avatars/avatar_u8iR8DacSYjsphyDqQTQ9?_a=BAMAMicg0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":2}},{"@type":"Comment","text":"A — Increasing max_connections is not a scaling solution — it is a RAM tradeoff. Aurora allocates memory per connection. Raising the limit consumes more RAM per additional connection, degrading query performance for everyone. More critically, Lambda’s ephemeral execution model means every cold start opens a new connection and every scale-out event adds connections. The ceiling gets hit again the next time concurrency grows.","datePublished":"2026-08-29T18:00:00.012Z","url":"https://daily.dev/posts/00fF6RtH4#c-PXpjOtipJ","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":2}}],"isPartOf":{"@type":"WebPage","url":"https://daily.dev/sources/iac4jsbu0lv8wbsc85fsh","name":"Joud Awad"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Joud Awad","item":"https://daily.dev/sources/iac4jsbu0lv8wbsc85fsh"},{"@type":"ListItem","position":3,"name":"Day 29/30 AWS System Design Patterns"}]}
```

