Serverless on AWS: lessons from building a SaaS platform from scratch
I designed and deployed a full SaaS platform using serverless architecture on AWS. Here I share the technical decisions, mistakes I made, and what I learned.
Uriel Arana
June 1, 2025
Serverless on AWS: lessons from building a SaaS platform from scratch
When I joined AppWhoop as a senior consultant, the challenge was clear: build a collaborative economy SaaS platform from scratch that could handle high concurrency — without the cost of always-on dedicated servers.
The answer was serverless architecture on AWS. But as you'll learn, "serverless" doesn't mean "problem-free."
Why Serverless?
For an early-stage SaaS, the benefits are clear:
- Pay per use: you only pay when there's real traffic
- Auto-scaling: AWS handles spikes without manual configuration
- Less DevOps: no servers to manage, no patches, no OS updates
But it has important tradeoffs you need to understand before committing.
The Architecture We Chose
React.js (Vite) → CloudFront (CDN)
↓
API Gateway → Lambda Functions
↓
MariaDB (RDS in private VPC)
S3 (static files and uploads)
CloudWatch (logs and alerts)
Three environments from day one
A mistake I see frequently: starting with only one environment. We configured three from day 1:
- Development —
developbranch, automatic deploy on every push - QA —
stagingbranch, manual deploy with approval - Pre-production —
mainbranch, production mirror for final testing
This saved us multiple times from critical bugs that only appear with real data.
Lesson 1: Lambda Cold Starts Are Real
The most underestimated problem with Lambda: cold starts. When a function hasn't been invoked in ~15 minutes, the next request takes an extra 800ms–3s to "wake up" the container.
Solution we implemented:
// Provisioned Concurrency for critical auth routes
// serverless.yml
functions:
auth:
handler: src/handlers/auth.handler
provisionedConcurrency: 2 # Always 2 "warm" instances
events:
- http:
path: /auth/{proxy+}
method: any
For less critical routes (dashboards, reports), we accepted the cold start and set team expectations accordingly.
Lesson 2: RDS in VPC + Lambda in VPC = Much Worse Cold Starts
This was our most costly mistake. We put RDS (MariaDB) inside a private VPC for security — correct. But Lambda also needs to be in the VPC to connect. And Lambda in a VPC has cold starts of 8–10 seconds.
The solution: RDS Proxy
Lambda (outside VPC) → RDS Proxy (in VPC) → RDS MariaDB
RDS Proxy maintains a persistent connection pool, eliminates the need to put Lambda in the VPC, and dramatically improves cold starts.
Additional cost: ~$35/month. Worth every cent.
Lesson 3: Structure Lambdas as Microservices, Not a Monolith
The most common anti-pattern: one giant Lambda that handles everything.
❌ handler.ts → handles auth, users, products, payments, reports
We organized each Lambda by business domain:
✅
handlers/
auth/ → login, registration, token refresh
users/ → user CRUD
listings/ → service listing CRUD
payments/ → payment processor integration
notifications/→ emails and push notifications
Benefit: each function scales independently. If there's a registration spike, only the auth Lambda scales. The rest are unaffected.
The Final Numbers
After 3 months in production:
- P99 Latency: < 200ms (excluding cold starts on non-critical functions)
- Uptime: 99.97%
- Monthly cost: ~$180 (for ~50k requests/day)
- Equivalent on EC2: ~$450/month for the same performance with auto-scaling
When NOT to Use Serverless
It would be dishonest not to mention this. Serverless is not the right answer for:
- Apps with persistent WebSocket connections (use EC2 + Socket.io)
- Video/audio processing (Lambda has 15 min limit and 10GB memory cap)
- Very early-stage startups that need to iterate fast without thinking about infra (use Railway or Render)
- Ultra-low, constant latency workloads (gaming, real-time trading)
Conclusion
Serverless on AWS let us launch a robust product with a small team and predictable costs. The key was understanding the tradeoffs from the start and not treating Lambda like a traditional server.
If you're considering this architecture for your next SaaS, the biggest piece of advice I can give: set up your 3 environments from day 1 and add RDS Proxy if you're using a relational database in a VPC.
Have questions about the architecture? Contact me here — I love talking distributed systems.
Uriel Arana is a Senior Full Stack Developer and Technology Consultant with experience in serverless architectures on AWS. Currently available for consulting projects.