<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: isola pelumi</title>
    <description>The latest articles on DEV Community by isola pelumi (@isola_pelumi_43595cdbff0c).</description>
    <link>https://dev.to/isola_pelumi_43595cdbff0c</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1871038%2Fc9db51db-0734-4d8d-96d3-c63784fbea10.jpg</url>
      <title>DEV Community: isola pelumi</title>
      <link>https://dev.to/isola_pelumi_43595cdbff0c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/isola_pelumi_43595cdbff0c"/>
    <language>en</language>
    <item>
      <title>Serverless vs Servers on AWS: What's the Difference and When Should You Use Each?</title>
      <dc:creator>isola pelumi</dc:creator>
      <pubDate>Mon, 19 Oct 2026 23:22:22 +0000</pubDate>
      <link>https://dev.to/isola_pelumi_43595cdbff0c/serverless-vs-servers-on-aws-whats-the-difference-and-when-should-you-use-each-2gkp</link>
      <guid>https://dev.to/isola_pelumi_43595cdbff0c/serverless-vs-servers-on-aws-whats-the-difference-and-when-should-you-use-each-2gkp</guid>
      <description>&lt;p&gt;If you're new to AWS, two words come up constantly: &lt;strong&gt;servers&lt;/strong&gt; and &lt;strong&gt;serverless&lt;/strong&gt;. They sound like opposites, and in some ways they are. But the real difference isn't about hardware. It's about &lt;strong&gt;who manages what&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this post we'll cover what each one is, how they differ in scaling, cost, and operations, and how to choose between them.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a "server" in AWS?
&lt;/h2&gt;

&lt;p&gt;A server is a computer that runs your code and responds to requests. On AWS, the classic server is an &lt;strong&gt;Amazon EC2 instance&lt;/strong&gt;: a virtual machine you rent from AWS.&lt;/p&gt;

&lt;p&gt;When you use EC2, you choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The instance type (CPU, memory, network)&lt;/li&gt;
&lt;li&gt;The operating system (Amazon Linux, Ubuntu, Windows)&lt;/li&gt;
&lt;li&gt;The storage and networking setup&lt;/li&gt;
&lt;li&gt;The software that runs on it (Node.js, Python, Nginx, a database)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then you are responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patching the operating system and keeping it secure&lt;/li&gt;
&lt;li&gt;Installing and updating your runtime and dependencies&lt;/li&gt;
&lt;li&gt;Scaling it, either manually or with Auto Scaling groups and load balancers&lt;/li&gt;
&lt;li&gt;Monitoring it and replacing it when it breaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key point is that &lt;strong&gt;the server keeps running, and you pay for it, whether anyone is using your app or not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other server-based AWS services:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon ECS / EKS on EC2&lt;/strong&gt;: container orchestration where you manage the underlying instances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon RDS&lt;/strong&gt;: managed databases that still run on provisioned instances you size yourself&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elastic Beanstalk&lt;/strong&gt;: easier deployment, but it still runs on EC2 under the hood&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is "serverless" in AWS?
&lt;/h2&gt;

&lt;p&gt;Here's the first thing to clear up: &lt;strong&gt;serverless does not mean there are no servers.&lt;/strong&gt; Of course there are servers. You just don't manage them.&lt;/p&gt;

&lt;p&gt;In a serverless model, AWS takes care of provisioning, patching, scaling, and availability. You focus on your code and your data. Serverless services typically share these traits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No server management.&lt;/strong&gt; You never SSH into a machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic scaling.&lt;/strong&gt; From zero requests to thousands, the service scales for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay for what you use.&lt;/strong&gt; You're billed for actual usage (requests, execution time, data stored or read), not for idle capacity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in high availability.&lt;/strong&gt; The services run across multiple Availability Zones by default.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Core serverless services on AWS:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Serverless service&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Run code&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AWS Lambda&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run containers&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;AWS Fargate&lt;/strong&gt; (with ECS or EKS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build APIs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Amazon API Gateway&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Store files&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Amazon S3&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NoSQL database&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Messaging and queues&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Amazon SQS, SNS, EventBridge&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflows&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AWS Step Functions&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Amazon Cognito&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's the difference at a glance. The coral boxes are what you manage. The teal boxes are what AWS manages for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fubexvipcya1q462uiett.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fubexvipcya1q462uiett.png" alt=" " width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With servers, you manage most of the stack. With serverless, you manage your code.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A tiny example: the same API, two ways
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Server approach (EC2)
&lt;/h3&gt;

&lt;p&gt;You launch an instance, install Node.js, copy your app over, and keep it running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// server.js - runs continuously on an EC2 instance&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from a server!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listening on port 3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need to configure security groups, set up a process manager like PM2 or systemd, and handle scaling and patching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serverless approach (Lambda)
&lt;/h3&gt;

&lt;p&gt;You write just the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lambda_function.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from serverless!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put API Gateway in front of it, and you have a working API. There is no machine to patch, and it scales from one request to many without any configuration from you.&lt;/p&gt;

&lt;p&gt;Here's a minimal AWS SAM template that defines it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2010-09-09'&lt;/span&gt;
&lt;span class="na"&gt;Transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Serverless-2016-10-31&lt;/span&gt;

&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;HelloFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Serverless::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lambda_function.lambda_handler&lt;/span&gt;
      &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3.12&lt;/span&gt;
      &lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;HelloApi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Api&lt;/span&gt;
          &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/hello&lt;/span&gt;
            &lt;span class="na"&gt;Method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Head-to-head comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;Servers (EC2)&lt;/th&gt;
&lt;th&gt;Serverless (Lambda, etc.)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You manage OS, patching, scaling&lt;/td&gt;
&lt;td&gt;AWS manages the infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configured by you (Auto Scaling)&lt;/td&gt;
&lt;td&gt;Automatic and fine-grained&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pricing model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pay for provisioned time, even when idle&lt;/td&gt;
&lt;td&gt;Pay per request and execution time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You pay while it runs&lt;/td&gt;
&lt;td&gt;Often close to zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Startup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always on, no cold starts&lt;/td&gt;
&lt;td&gt;Possible cold starts on first invocation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution limits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Essentially none&lt;/td&gt;
&lt;td&gt;Lambda has a maximum duration (15 minutes) and other limits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full control of OS and environment&lt;/td&gt;
&lt;td&gt;Limited to the runtime and settings offered&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Long-running, steady, or highly customized workloads&lt;/td&gt;
&lt;td&gt;Event-driven, spiky, or unpredictable workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The trade-offs in more detail
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Cost
&lt;/h3&gt;

&lt;p&gt;Serverless shines when traffic is &lt;strong&gt;unpredictable or low&lt;/strong&gt;. If your app gets 100 requests a day, you pay for roughly 100 requests, not a machine sitting idle 24/7.&lt;/p&gt;

&lt;p&gt;But the math can flip. If you have &lt;strong&gt;steady, high, constant traffic&lt;/strong&gt;, a well-utilized EC2 instance (especially with Savings Plans or Reserved Instances) can be cheaper than paying per-invocation at very high volume.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo9hiq1wrtceniyi4fdd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo9hiq1wrtceniyi4fdd3.png" alt=" " width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Illustrative only, not real AWS prices. A server costs the same whether it's busy or idle. Serverless cost grows with usage, so it wins at low or spiky traffic and can lose at very high, steady traffic.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Always model your real usage using the &lt;a href="https://calculator.aws/" rel="noopener noreferrer"&gt;AWS Pricing Calculator&lt;/a&gt; rather than assuming either option is cheaper.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Scaling
&lt;/h3&gt;

&lt;p&gt;With EC2, scaling means setting up Auto Scaling groups, load balancers, health checks, and scaling policies, and then tuning them. New instances take time to boot.&lt;/p&gt;

&lt;p&gt;With Lambda, each incoming request can trigger a new execution environment automatically, so scaling is largely hands-off. There are still account-level concurrency limits to be aware of.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cold starts
&lt;/h3&gt;

&lt;p&gt;When a Lambda function hasn't been invoked recently, AWS needs to spin up a fresh execution environment, which adds latency to that first request. This is called a &lt;strong&gt;cold start&lt;/strong&gt;. For many applications it's barely noticeable, but for latency-sensitive workloads it matters. Options like &lt;strong&gt;Provisioned Concurrency&lt;/strong&gt; and lighter runtimes can reduce the impact.&lt;/p&gt;

&lt;p&gt;Servers don't have this problem because they're already running.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Limits and control
&lt;/h3&gt;

&lt;p&gt;Lambda has constraints, including a maximum execution time of 15 minutes, limits on memory, and limits on deployment package size. You also can't install arbitrary system-level software the way you can on EC2.&lt;/p&gt;

&lt;p&gt;If you need a &lt;strong&gt;long-running process, a specialized OS configuration, GPU access, or software that needs deep system control&lt;/strong&gt;, servers are usually the better fit.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Operational burden
&lt;/h3&gt;

&lt;p&gt;This is serverless's biggest selling point. Fewer things to patch, fewer things to wake up for at 3 a.m. Your team spends time on features instead of infrastructure.&lt;/p&gt;

&lt;p&gt;That said, serverless isn't "ops-free." You still need to handle monitoring, logging, permissions (IAM), and debugging distributed, event-driven systems, which can be trickier than debugging one server.&lt;/p&gt;




&lt;h2&gt;
  
  
  So which should you choose?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose serverless when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic is spiky, unpredictable, or low&lt;/li&gt;
&lt;li&gt;You're building event-driven workflows (file uploads, queue processing, webhooks)&lt;/li&gt;
&lt;li&gt;You're building an MVP and want to move fast&lt;/li&gt;
&lt;li&gt;You have a small team that doesn't want to manage infrastructure&lt;/li&gt;
&lt;li&gt;Your tasks are short-lived&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choose servers when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have steady, predictable, high-volume traffic&lt;/li&gt;
&lt;li&gt;You need long-running processes&lt;/li&gt;
&lt;li&gt;You need full control over the environment, OS, or networking&lt;/li&gt;
&lt;li&gt;You're migrating a legacy application that expects a traditional server&lt;/li&gt;
&lt;li&gt;You have specialized hardware requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;And don't forget the middle ground.&lt;/strong&gt; AWS Fargate lets you run containers without managing servers, which is a good option when you want container flexibility with a serverless-style operating model.&lt;/p&gt;




&lt;h2&gt;
  
  
  You don't have to pick just one
&lt;/h2&gt;

&lt;p&gt;Most real-world architectures are &lt;strong&gt;hybrid&lt;/strong&gt;. A typical setup might look like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;React frontend&lt;/strong&gt; hosted on S3 + CloudFront (serverless)&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;API&lt;/strong&gt; built with API Gateway + Lambda (serverless)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;message queue&lt;/strong&gt; on Amazon SQS to hand off slow jobs (serverless)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;long-running background worker&lt;/strong&gt; on ECS or EC2 (server-based)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;relational database&lt;/strong&gt; on Amazon RDS (server-based)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffs3yeqtb8r98c49njxs3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffs3yeqtb8r98c49njxs3.png" alt=" " width="799" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A typical hybrid: serverless for the frontend and API, servers for long-running work and the relational database.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Use serverless where it fits naturally, and servers where you need control or predictable cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server (EC2)&lt;/strong&gt; means you rent and manage a virtual machine. You get maximum control, but also maximum responsibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless (Lambda, Fargate, DynamoDB, and more)&lt;/strong&gt; means AWS manages the infrastructure, and you pay for what you use.&lt;/li&gt;
&lt;li&gt;"Serverless" doesn't mean no servers. It means &lt;em&gt;you&lt;/em&gt; don't manage them.&lt;/li&gt;
&lt;li&gt;Serverless excels at spiky, event-driven workloads. Servers excel at steady, long-running, or highly customized ones.&lt;/li&gt;
&lt;li&gt;The best architectures often combine both.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're just starting out, build something small with Lambda and API Gateway. It's one of the fastest ways to understand the difference firsthand.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>cloud</category>
      <category>cloudengineering</category>
    </item>
    <item>
      <title>🚨 Cron Jobs Don’t “Catch Up” and This Can Break Your App</title>
      <dc:creator>isola pelumi</dc:creator>
      <pubDate>Sat, 17 Jan 2026 20:23:21 +0000</pubDate>
      <link>https://dev.to/isola_pelumi_43595cdbff0c/cron-jobs-dont-catch-up-and-this-can-break-your-app-1g7j</link>
      <guid>https://dev.to/isola_pelumi_43595cdbff0c/cron-jobs-dont-catch-up-and-this-can-break-your-app-1g7j</guid>
      <description>&lt;p&gt;One thing many developers misunderstand about cron jobs &amp;amp; schedulers is how they behave when a server goes down.&lt;/p&gt;

&lt;p&gt;If your server is down, cron jobs DO NOT run.&lt;br&gt;
When the server comes back up, cron does NOT replay missed jobs.&lt;/p&gt;

&lt;p&gt;Those jobs are simply gone.&lt;br&gt;
How cron actually works&lt;br&gt;
Cron doesn’t track time or remember history.&lt;br&gt;
It simply: Wakes up, Checks the current system time, Runs jobs that match now and Goes back to sleep. No memory, no backlog, no forgiveness.&lt;/p&gt;

&lt;p&gt;A common mistake&lt;br&gt;
Relying on cron for exact execution:&lt;br&gt;
“At 12:00 AM, expire subscriptions”&lt;br&gt;
“At midnight, generate reports”&lt;br&gt;
“At 9 AM, send reminders”&lt;br&gt;
If the server is down at that moment  nothing happens.&lt;/p&gt;

&lt;p&gt;How production systems handle this&lt;br&gt;
The fix isn’t “better cron”.&lt;br&gt;
The fix is better design.&lt;br&gt;
Cron should be a trigger not the source of truth.&lt;br&gt;
Instead of:&lt;br&gt;
Cron → Do the job&lt;/p&gt;

&lt;p&gt;Use:&lt;br&gt;
Cron → Check database state → Process pending work&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
Run cron every 5 minutes&lt;br&gt;
Query the DB for records that should have been processed&lt;br&gt;
Handle them safely&lt;/p&gt;

&lt;p&gt;If the server was down:&lt;br&gt;
Data still exists&lt;br&gt;
Job runs when the server is back&lt;br&gt;
Nothing is lost&lt;br&gt;
Key production principles&lt;br&gt;
i. Cron is stateless&lt;br&gt;
ii. Jobs must be idempotent&lt;br&gt;
ii. Time should be UTC&lt;br&gt;
iii. Business logic should rely on data state, not exact timing&lt;br&gt;
iv. Heavy work belongs in queues, not cron&lt;/p&gt;

&lt;p&gt;Mental model&lt;br&gt;
Cron is like an alarm clock without memory If you’re asleep when it rings, it won’t remind you later.&lt;/p&gt;

&lt;p&gt;If you’re building: Subscription systems, Payment retries, Reports, Background jobs, AI batch processing and you rely purely on cron timing you’re risking silent failures.&lt;/p&gt;

&lt;p&gt;Design for downtime, not perfection.&lt;br&gt;
In my next post I will be discussing CRON VS Queue.&lt;/p&gt;

&lt;p&gt;hashtag#BackendEngineering hashtag#SystemDesign hashtag#NodeJS hashtag#CronJobs hashtag#DistributedSystems hashtag#SoftwareEngineering.  &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
