How to Keep Your AWS Lambdas Warm with GitHub Actions (And Why You're Committing Architectural Heresy)
Matthias Bigl

Matthias Bigl

62 views

How to Keep Your AWS Lambdas Warm with GitHub Actions (And Why You're Committing Architectural Heresy)

Let's get one thing straight before we write a single line of YAML:

If you are doing this, you are defeating the entire purpose of serverless.

Language: text

You chose AWS Lambda because you wanted it to scale to zero. You wanted to pay only for exactly what you use. But then your user clicked a button, stared at a loading spinner for four seconds, and closed the tab.

Now you're here, looking up how to keep AWS Lambdas warm using GitHub Actions scheduled workflows, effectively building a weird Rube Goldberg machine to simulate a server that never turns off.

Theo would look at you through his webcam, sigh, and say:

"Bro. Just use a persistent server. Put it on Railway or Vercel. You are not Google. Stop playing cloud architect."

The Primeagen would look at your 4-second boot time and say:

"Skill issue. If you didn't write it in a garbage-collected language and just used Rust, it would be blazingly fast and you wouldn't need a cron job to keep it alive."

Both of them are right.

But neither of them is here to pay your AWS bill or rewrite your legacy Node.js backend.

So, out of morbid curiosity, let's explore how this actually works, what AWS is doing under the hood, and whether you should ever ship this crime against cloud computing.

The Truth About Cold Starts (It's a Tiny Linux Server)

A common myth is that AWS has to boot a virtual machine from absolute zero every time a Lambda cold start happens.

That's not actually true.

AWS uses Firecracker, their open-source microVM technology, and maintains a massive pool of pre-warmed generic microVMs ready to be claimed.

When a request arrives, AWS doesn't boot a VM from scratch. Instead, it grabs one of those tiny Linux environments and prepares it to run your function.

The cold start delay happens in the next steps.

Loading diagram...

Language: mermaid

The slow part typically includes:

  • Downloading and unpacking your code
  • Attaching ENIs if you're inside a VPC
  • Booting the runtime (Node, Python, etc.)
  • Running initialization code
  • Opening database connections
  • Parsing dependencies

If your Lambda has 300MB of dependencies and a database client, that initialization step can easily take several seconds.

The Key Trick

AWS usually keeps Lambda execution environments alive for roughly 5–15 minutes after a request.

If we invoke the Lambda every 5 minutes, AWS never tears down the environment.

Meaning the next real user request hits a warm runtime instead of triggering a cold start.

This is the entire hack.

Keeping a Lambda warm with a cron job is just running a server with extra steps.

The Philosophical Crisis: Should You Actually Do This?

By pinging your Lambda every 5 minutes, you're effectively saying:

"I want an always-on server, but I want it to run on Lambda and pretend it's serverless."

There are a few legitimate reasons you might do this.

Reasons You Might Actually Do This

You're broke

A GitHub Action hitting a Lambda every 5 minutes results in:

  • 8,640 requests per month

Assuming:

  • 50ms runtime
  • 1GB Lambda

That's about 432 GB-seconds of compute.

The AWS free tier gives you:

  • 1,000,000 requests
  • 400,000 GB-seconds

Meaning this costs exactly $0.

And $0 > $5 VPS.

You're trapped

Your company mandated serverless architecture, but your product manager is angry about the loading spinner and nobody wants to pay for Provisioned Concurrency.

This hack improves UX without touching infrastructure budgets.

You're wrapping a bloated API

Sometimes you inherit a giant Java or Python library that takes 4–6 seconds to initialize.

A rewrite isn't happening this sprint.

So you cheat.

Reasons You Should Absolutely Not Do This

The concurrency blind spot

This hack only keeps one instance warm.

If two users hit your API simultaneously:

  • User A → warm instance
  • User B → cold start

Lambda will spin up a second microVM and the problem returns.

You're reinventing a worse EC2 instance

If your service needs to be ready 24/7 with low latency, a small persistent container is often the better architecture.

You're masking the real problem

If cold starts ruin your UX, the issue is often:

  • oversized dependencies
  • large container images
  • slow initialization logic

GitHub Actions cron isn't perfect

Scheduled workflows can be delayed during peak hours.

You will still get occasional cold starts.

Just fewer of them.

The Architecture of the Hack

The trick is simple.

GitHub Actions periodically pings your Lambda, which prevents AWS from shutting down the runtime.

Loading diagram...

Language: mermaid

Step 1: The Warmup Short-Circuit

You don't want your warmup request triggering heavy logic or database queries.

Add a fast early return in your Lambda handler.

// handler.js

export const handler = async (event) => {
  // Catch the warmup ping
  if (event?.source === "warmup") {
    console.log("The tiny Linux server is awake.");
    return { statusCode: 200, body: "warm" };
  }

  // Your actual logic here
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: "Hello from a warm Lambda!",
    }),
  };
};

Language: text

Step 2: Store Your Secrets

Go to:

GitHub Repo → Settings → Secrets and variables → Actions

Create a secret called:

LAMBDA_URL

Language: text

This should contain your API Gateway endpoint or Lambda Function URL.

Do not hardcode it in the workflow.

We may be committing architectural sins, but we still follow basic security practices.

Step 3: The GitHub Actions Workflow

Create:

.github/workflows/keep-lambda-warm.yml

Language: text

name: Keep Lambda Warm 🔥

on:
  schedule:
    - cron: "*/5 * * * *"
  workflow_dispatch:

jobs:
  warm-lambda:
    name: Ping the tiny Linux server
    runs-on: ubuntu-latest

    steps:
      - name: Ping Lambda via HTTP
        run: |
          response=$(curl -s -o /dev/null -w "%{http_code}" \
            -X POST "${{ secrets.LAMBDA_URL }}" \
            -H "Content-Type: application/json" \
            -d '{"source": "warmup"}')

          echo "Response code: $response"

          if [ "$response" -ne 200 ]; then
            echo "Lambda returned $response — we are completely cooked."
            exit 1
          fi

          echo "Lambda is warm. The microVM lives."

Language: text

Step 4: Invoking a Private Lambda (Inside a VPC)

If your Lambda has no public endpoint, invoke it using the AWS CLI.

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: ${{ secrets.AWS_REGION }}

- name: Invoke Lambda directly
  run: |
    aws lambda invoke \
      --function-name my-unnecessarily-serverless-function \
      --payload '{"source": "warmup"}' \
      --cli-binary-format raw-in-base64-out \
      response.json

    cat response.json

Language: text

The Verdict

Using GitHub Actions to keep AWS Lambdas warm is the ultimate "I refuse to pay for Provisioned Concurrency" hack.

Is it smart?

Financially, yes. It costs zero dollars.

Is it good architecture?

Absolutely not.

You are fighting the platform's core design, and the illusion collapses the moment multiple users hit your API simultaneously.

If you find yourself deploying 15 cron jobs just to keep a fleet of Lambdas alive, take a step back.

Stop fighting the cloud.

Spin up a persistent container.

Or go full Primeagen mode, open NeoVim, rewrite the whole thing in Rust, and boot in 12 milliseconds.

Until then:

Enjoy your artificially warm Firecracker microVM. 🔥

Matthias Bigl

Matthias Bigl

Insert pretentious stuff about yourself here

Leave a Reply

Bigl's Blog

Personal blog by Matthias Bigl — Exploring technology, software development, and innovation. bigls.net

© 2026 Matthias Bigl. All rights reserved.

Connect with Matthias Bigl

Bigl's Blog is the personal technology blog of Matthias Bigl (bigls.net), featuring articles on software development, web technologies, and tech insights.