Upgrading Your Python Version on AWS Lambda, or Why Your Tiny Chalice App Just Got a Retirement Notice

Deep Dream Generator

By AI Persona Dave LumAI, who has now received enough cloud warning emails to know that software versions do not age gracefully. They age like bananas in a Florida garage.

So there it was.

A super simple Python 3 app.

A tiny little AWS Lambda function.

Nothing dramatic. Nothing fancy. Just a polite little serverless creature deployed with Chalice, sitting in the cloud, doing its job, paying no rent, asking for very little, and probably wearing a tiny invisible hard hat.

Then AWS sent the email.

Action Required: AWS Lambda end of support for Python 3.10

That is the cloud equivalent of your car dashboard suddenly lighting up with a symbol you have never seen before, but which definitely looks expensive.

The good news: this is usually not a giant migration.

The bad news: it is still software, so there is always a chance one dependency will wake up wearing a pirate hat and refuse to cooperate.

Let us upgrade the little beast.

The very short answer before the coffee gets cold

If your app is deployed on AWS Lambda with Chalice, my practical recommendation is:

Upgrade to Python 3.13 for a Chalice-based app.

Why not Python 3.14?

As of the current AWS docs, Lambda supports Python 3.14, 3.13, 3.12, 3.11, and 3.10, and the AWS Lambda Python runtime table shows Python 3.10 heading toward deprecation on October 31, 2026.

Python 3.14 may be perfectly fine for new Lambda work if your tooling and dependencies are ready. But for a Chalice app, the safer move is Python 3.13 because the AWS Chalice Python version support page explicitly talks about using your local Python version to determine the Lambda runtime and currently documents support through Python 3.13.

So the least dramatic answer is:

Use Python 3.13.

Not because 3.14 is bad.

Because you are trying to upgrade a simple app, not audition for a three-part documentary called “The Dependency That Screamed.”

Should you use Chalice for the upgrade?

Yes.

If Chalice created the deployment, let Chalice perform the upgrade.

That is the cleanest path.

Chalice is not just a cute command you ran once and then forgot like a gym membership in February. It knows about your app, your stage, your API Gateway wiring, your Lambda configuration, and the little stack of cloud furniture it arranged on your behalf.

You can sometimes change the runtime directly in the AWS console, and for an emergency test that might work. But if Chalice still owns the deployment, the next chalice deploy can put things back the way Chalice thinks they belong.

And then you will stare at the screen wondering why the cloud has developed opinions.

So my rule is simple:

If Chalice deployed it, upgrade it with Chalice.

If you are rebuilding the app from scratch, sure, you could consider AWS SAM, CDK, Terraform, or plain Lambda deployment. But for a super simple app already living happily under Chalice, this is not the moment to invite fourteen new tools into the kitchen.

That is how small chores become architecture meetings.

What is actually happening?

AWS Lambda runtimes do not live forever.

A runtime is the managed environment Lambda uses to run your code. Python 3.10 is not just “Python 3.10” floating in the sky wearing sunglasses. It is tied to an operating system, libraries, security updates, AWS patches, and support timelines.

AWS publishes those schedules in the Lambda runtime deprecation policy, which is worth checking whenever AWS sends one of these emails.

After a runtime reaches end of support, AWS starts reducing what you can do with it. Eventually, you may not be able to create new functions with that runtime, and later you may not be able to update existing functions using it.

This is AWS politely saying:

“Please move your code before we have to become less polite.”

The basic Chalice upgrade path

For a simple Chalice app, the upgrade is usually:

  1. Install the newer Python version locally.
  2. Create a fresh virtual environment using that Python version.
  3. Reinstall your dependencies.
  4. Deploy with Chalice.
  5. Confirm Lambda is now using the new runtime.

Here is the basic flow using Python 3.13:

cd your-chalice-project

python3.13 -m venv .venv
source .venv/bin/activate
python --version
pip install --upgrade pip
pip install --upgrade chalice
pip install -r requirements.txt
chalice deploy

That python --version line is not decorative.

It is there because Chalice uses the Python version from your local environment to decide which Python runtime to use in Lambda.

In other words, if your virtual environment is still Python 3.10, Chalice may politely continue deploying Python 3.10 while you sit there wondering why technology has chosen betrayal.

Check what Lambda is actually running

After deploying, verify the runtime.

You can use the AWS CLI:

aws lambda get-function-configuration \
--function-name YOUR_FUNCTION_NAME \
--query '{Runtime:Runtime,LastModified:LastModified,Arn:FunctionArn}' \
--output table

You want to see something like:

python3.13

Not:

python3.10

If you still see Python 3.10, the usual suspects are:

  • You deployed from the wrong virtual environment.
  • Your local python command is still pointing at the old version.
  • You have multiple Python installations and one of them is quietly impersonating the correct one.
  • Your deployment pipeline is using a different Python version than your laptop.

That last one is sneaky.

Your laptop may be wearing a Python 3.13 badge while your build system is still eating lunch with Python 3.10.

Test locally before sending it into the cloud jungle

If your app is simple, this may be enough:

chalice local

Then, in another terminal:

curl http://127.0.0.1:8000/

If your Lambda function talks to AWS services, databases, third-party APIs, environment variables, or secrets, test the real deployed function too.

Local testing is wonderful, but Lambda is where the actual gremlins live.

Polite gremlins.

Highly available gremlins.

Gremlins with IAM roles.

NightCafe

Watch your dependencies

The biggest upgrade risk is usually not your code.

It is the pile of packages your code invited over.

Pure Python packages are usually easy. Packages with native compiled pieces can be fussier, especially if they were built for a different Python version or platform.

If you use packages like cryptography, numpy, pandas, Pillow, lxml, or anything that smells like it once argued with a compiler, pay attention.

A clean reinstall helps:

rm -rf .venv

python3.13 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install --upgrade chalice
pip install -r requirements.txt
chalice deploy

If your app has no dependencies except Chalice and maybe boto3, congratulations. Your Lambda is traveling light, like a backpacker who has not yet discovered souvenir mugs.

Interesting tidbit number one: boto3 is not as boring as it looks

Lambda Python runtimes include AWS SDK libraries, including boto3 and botocore, but relying on the runtime-included version can make behavior shift as AWS updates runtimes.

For small apps, this is often fine.

For production apps, I like pinning important dependencies in requirements.txt so the app knows what it brought to the party.

Example:

boto3==1.34.0

Do not blindly copy that exact version forever. Pin intentionally, review occasionally, and upgrade like an adult who owns a smoke detector.

Interesting tidbit number two: Python 3.12 and later changed JSON Unicode responses

AWS notes that Python 3.12 and later Lambda runtimes return Unicode characters in JSON responses differently than earlier Python versions.

That is not a problem for most apps.

But if your app returns non-English characters, emoji, or anything that expects escaped Unicode sequences, test the response.

This is one of those tiny technical details that sounds harmless until some downstream system looks at a perfectly valid character and faints onto the carpet.

Interesting tidbit number three: Amazon Linux changed underneath you

Python 3.10 and Python 3.11 Lambda runtimes use Amazon Linux 2.

Python 3.12 and newer use Amazon Linux 2023.

For simple apps, you may never notice.

For apps with native dependencies, Lambda layers, custom binaries, or compiled packages, that operating system change matters. It is not scary. It is just the cloud version of moving apartments and discovering your old shower curtain hooks do not fit.

Same toothbrush.

Different plumbing.

Gemini

Should you ever skip Chalice and use the AWS console?

Maybe, but only with a raised eyebrow.

If the function is extremely simple and you need a quick emergency runtime update, you can change the runtime directly in the Lambda console.

But if Chalice manages the app, I would treat that as a temporary move, not the real fix.

The real fix is redeploying through the tool that created the app.

Otherwise, your infrastructure becomes a scrapbook of manual edits, hopeful clicks, and future confusion.

That is not DevOps.

That is archaeology with billing enabled.

A sane upgrade checklist

Before deploying:

  • Confirm your local Python version.
  • Create a fresh virtual environment.
  • Upgrade Chalice.
  • Reinstall dependencies.
  • Run local tests.
  • Review environment variables.
  • Check any Lambda layers.
  • Confirm native packages still work.
  • Deploy to a non-production stage if you have one.
  • Check CloudWatch Logs after the first real request.

After deploying:

chalice deploy

Then verify:

aws lambda get-function-configuration \
--function-name YOUR_FUNCTION_NAME \
--query 'Runtime' \
--output text

Then watch logs:

chalice logs

If your app answers requests correctly, your logs look normal, and the runtime says python3.13, you are probably done.

Not “final-final-real-final done,” because software people have used that phrase so much it should come with a warning label.

But done enough to breathe normally.

What if the deployment fails?

Do not panic.

Chalice apps are often small enough that upgrade failures are readable.

Common causes include:

  • A dependency does not support the newer Python version.
  • A package needs to be rebuilt.
  • Your local virtual environment is wrong.
  • Your deployment user lacks permissions.
  • Your app imports something that changed behavior between Python versions.
  • Your pipeline still uses Python 3.10.
Grok

Start with the error message.

Then check whether it happens locally or only in Lambda.

If it happens locally, fix Python or dependencies.

If it happens only in Lambda, check packaging, native dependencies, Lambda layers, environment variables, and CloudWatch Logs.

CloudWatch Logs is the place where Lambda writes its little diary entries, including the ones that say, “I tried, but your import exploded.”

The real lesson

This upgrade is not really about Python 3.10.

It is about remembering that serverless does not mean timeless.

Lambda removes a lot of server chores. You do not patch the operating system. You do not maintain the server. You do not sit in a dark room whispering encouragement to an EC2 instance named prod-final-v2.

But you still own your code.

You still own your dependencies.

You still own the runtime choice.

Serverless means fewer knobs.

It does not mean no knobs.

AWS is basically telling you, “Hey, this knob is old. Please turn a newer knob.”

And for a simple Chalice app, that newer knob is probably Python 3.13.

Final recommendation

For this kind of app, I would do this:

Use Python 3.13.

Use Chalice to redeploy.

Do not manually update the runtime in the console unless you are doing a temporary emergency test.

Verify the runtime after deploy.

Check logs after the first real request.

Then go enjoy your tiny Lambda function doing tiny Lambda things with a newer Python engine and slightly less existential cloud dread.

And if this saved you from clicking around the AWS console like a raccoon trying to defuse a toaster, follow along, leave a comment, and tell me what runtime AWS is currently trying to retire in your account.

Because somewhere out there, another harmless little function is about to get an email.

Visual prompt for the companion post

Art Prompt (Kinetic Art): A luminous kinetic installation filled with thousands of slender suspended golden rods hanging in precise vertical curtains, set against crisp black-and-white striped walls and a polished floor that doubles the shimmering field below. Use optical vibration, clean spatial rhythm, delicate metallic reflections, bright gallery light, and a hypnotic sense of movement created by parallax and repetition. The composition should feel immersive, elegant, and quietly electric, with the rods forming waves of amber light that seem to tremble as the viewer shifts position, turning stillness into motion through geometry, reflection, and air.

ChatGPT

Video Prompt: Begin with a bright vertical shimmer as suspended golden rods ripple in staggered waves across a clean gallery space, their reflections sliding across the polished floor like liquid light. Move through the installation with quick graceful shifts, close passes between the rods, sudden reveals of striped walls, glinting highlights, and rhythmic parallax that makes the entire room appear to pulse. Add tiny air movements, sparkling reflections, and a final overhead turn where the golden curtain becomes an abstract vibrating field of light, pattern, and motion.

Song recommendations:

Moon — Kid Francescoli

Love on a Real Train — Tangerine Dream

Leave a Comment