Serverless is (sort of) stupid

Trying to do everything on serverless functions is just stupid

I'll admit, this story does come from a salty place, but I tried my best to be fair when writing this, and to be clear I'm talking about "Functions-as-a-service" when referring to serverless here

Part 1: The issue

The thing I see the most these days is people wanting to deploy a full server on, well, serverless functions, where it just doesn't make sense to do so.

In my opinion, serverless functions are just that, functions. You don't code a whole application inside a single function, just like you don't deploy an API inside a serverless. What you do instead is split your application's code into small, reusable functions and combine them to solve your problem.

Part 2: Where I love serverless

If I have a task that needs to scale well, needs tons of resources if there's a large load that I just can't handle on my small server, or would be inconvenient to use in a traditional server, I'll use a serverless function, because THIS is what serverless was intended for.

A practical example would be having a function that would scrape a website for data and then trigger a rebuild with the new data / send that data to the client to consume (SSG / CSR). Here, it's not practical to be running a server to serve those files just because I want to, practically, run a function. In this case, even hosting on a traditional express/NestJS/Your favourite server, you'd be making a call to an endpoint for one function that you can't run in a browser. Instead, you're benefiting from a CDN that serves your static files, while having some backend functionality for your data.

Another example would be an SPA built with your favourite framework that needs just one backend functionality (Payments, sending email, resizing images, etc.), where it would be stupid if you DON'T use serverless.

One example where I planned on using serverless had I made the project was using puppeteer to scrape GitHub's trending repos. I'd cache that every day and present it to a user in a Tinder-style format, and recommending some other repos based on what they liked. The function was simple and it had one job to do: Open Chrome, go to GitHub, return the data.

Part 3: Where I hate serverless

Trying to deploy an API, that needs a database, sessions, and file-storage, into a serverless function. It's like being given a crop-duster and being told "Go to the moon", because now instead of managing a single server with a database, storage, and your API, you're managing a server with your database (or paying for a managed database), a storage-bucket service, and your serverless functions, and along with all of that, we've got a frustrated team looking through hundred-line logs to figure it why X isn't working with Y to go to Z.

"But it's cheaper!" Are you sure?

Part 4: Pricing breakdown

Serverless

MongoDB

  • Managed MongoDB: $9-25/mo (Shared cluster, MongoDB Atlas, excluding free-tier) OR
  • Unmanaged MongoDB: $5/mo (Digital Ocean's cheapest VPS)

Redis

  • Managed Redis: $12.41/mo (AWS ElastiCache, 1 t2.micro node, Billed at $0.017 per hour) OR
  • Unmanaged Redis: $5/mo (Digital Ocean's cheapest VPS, $0 if you used it for MongoDB)

Storage

  • AWS S3: $5.76/mo (250gb, 1000 PUT requests, 5000 GET requests)
  • AWS Data transfer: $0.36/mo (1gb inbound, 5gb outbound, so approx. 1mb per request if you factor in request amount above)
  • Total: $6.12/mo

Total

  • Managed Databases: $17 + $12.41 + $6.12 = $35.53/mo ($426.36/yr) - $17 is MongoDB's average price assuming you upgrade halfway through the year
  • Unmanaged Databases: $5 + $6.12 = $11.12/mo ($133.44/yr)

Servers (Digital Ocean)

API, MongoDB, Redis

  • Shared VPS: $5/mo (1 CPU, 1gb RAM, 25gb SSD, 1TB Transfer)
  • Shared VPS 2: $20/mo (2 CPU, 4gb RAM, 80gb SSD, 4TB Transfer)

Storage

  • Cheapest plan: $5/mo (250gb, 1TB outbound, unlimited inbound, $0.02/gb Storage overage, $0.01/gb Outbound overage)

Total

  • $5 + $5 = $10/mo ($120/yr)
  • $20 + $5 = $25/mo ($300/yr)

But wait, it IS cheaper

Yeah, I was being generous. If you needed DO's 1TB outbound transfer, that would be $92.07/mo, or $1,104.84/yr, making the total:

  • Managed Databases: $17 + $12.41 + $97.83 = $127.24/mo ($1526.88/yr)
  • Unmanaged Databases: $5 + $97.83 = $102.83/mo ($1233.96/yr)

Your heart dropped yet? Yeah, I was kidding. If you use AWS CloudFront, you only pay $5.76 + CloudFront costs for storage, so:

  • $5.76 + ($0.116 * 1024gb) = $5.76 + $118.784 ~= $124.54

Where $0.116 is the average cost per GB from CloudFront

Wait...... This is even more expensive, and that's not counting MongoDB and Redis. Not to mention the slight vendor lock-in, your time spent on configuration and wiring it all up, and suddenly I'm starting to think just getting a VPS is cheaper. In fact, a $65/mo DigitalOcean Dedicated VPS gets you:

  • 8gb RAM
  • 2 CPUs
  • 50gb SSD
  • 4TB Transfer

And I'm sure this is enough for most medium-sized businesses to run on for a while. If you still need more, you can upgrade to a $130 VPS, a $260 VPS, or even more.

I thought I should mention that I'm not big enough to be sponsored by DigitalOcean, but I used them as an example since they're my favourite.

Final notes

I understand that pricing isn't the only benefit to serverless, and that you'll only pay for what you use, but in the pricing breakdown I tried to base AWS services on what DigitalOcean provides, and assumed that the traffic would be equal everyday. If you're running a simple app that might only get large amounts of traffic a certain time of the day, and you need to handle that load, that is a very nice usage of serverless, but for the general-purpose application that will be complicated enough, I think servers are still dominant. For now.

Thanks for reading :D

Abdullah T's photo

Nice article. Interesting perspective on your pricing comparasion, however, the issue is if you are building a production application in which you need to consider an array of different things such as durability, availability, redundancy, backups, single points of failure, your argument for a single server that holds "a database, storage, and your API" is not resilient.

Here are some counterpoints:

  • If your app scales, you will normally need to run a second server, and put a load balancer in front of it. In fact, in low scale its actually very good practice to run at least 2 servers (in separate Availability Zones) to increase availability in case a certain AZ goes down. So, when you scale more, you will need 3+ servers.
  • Having the DB in the same server of your application is generally against good practice. It's highly recommended to put a DB in a separate server, and also run a backup server db and ensure you constantly sync and backup your data. The headache of this makes it way more attractive to use a managed DB instead which will handle db updates, automated backups and give you easier ways to manage scaling.

So, the above couple points make the pricing argument not well balanced in the scenario of reliable highly available production apps.

Other favorable point for serverless is usage in apps that have seasonal peaks or low growth. Serverless scales nicely for unexpected demands with very low maintenance on your side. You also don't pay for idle resources, and it frees your time on maintenance so you can focus more on business value.

Anyways, while I love serverless, there are scenarios where using a server makes more sense, and these scenarios depend on the type of applications you will have. If you can't tolerate any cold start latencies, or if your app requires high memory and cpu requirements, or have long-running functions. Though serverless services in AWS come with different patterns and ways for you to build around these points.

Arvind Kumar 🌱's photo

Totally Agree

Daniel Ziltener's photo

There's no such thing as "serverless" anyway. Unless you're talking distributed systems.

Mohammed Ali Agha's photo

Yeah, "serverless" are just servers that you don't worry about, but the name isn't really a strong argument