<?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: ntoledo319</title>
    <description>The latest articles on DEV Community by ntoledo319 (@ntoledo319).</description>
    <link>https://dev.to/ntoledo319</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%2F3997589%2F5bdd25d8-a708-4db4-8311-e27a6be8b853.png</url>
      <title>DEV Community: ntoledo319</title>
      <link>https://dev.to/ntoledo319</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ntoledo319"/>
    <language>en</language>
    <item>
      <title>"error:0308010C:digital envelope routines::unsupported — why Lambda runtime upgrades break your webpack build"</title>
      <dc:creator>ntoledo319</dc:creator>
      <pubDate>Mon, 13 Jul 2026 07:17:03 +0000</pubDate>
      <link>https://dev.to/ntoledo319/error0308010cdigital-envelope-routinesunsupported-why-lambda-runtime-upgrades-break-your-18dh</link>
      <guid>https://dev.to/ntoledo319/error0308010cdigital-envelope-routinesunsupported-why-lambda-runtime-upgrades-break-your-18dh</guid>
      <description>&lt;p&gt;If you just bumped your CI pipeline — or your Lambda runtime — to Node.js 18 or 22 and your build step died, this is the wall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:67:19)
    at Object.createHash (node:crypto:130:10)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stack trace points into webpack, &lt;code&gt;react-scripts&lt;/code&gt;, or Jest. Your Lambda handler code is untouched. Here is why the runtime label change triggers a build failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cause in two sentences
&lt;/h2&gt;

&lt;p&gt;Node.js 17 switched from OpenSSL 1.1.1 to OpenSSL 3.0. Every Node.js version since — 18, 20, 22 — runs OpenSSL 3. OpenSSL 3 puts legacy algorithms including &lt;strong&gt;MD4&lt;/strong&gt; into a disabled-by-default "legacy provider." Webpack 4 calls &lt;code&gt;crypto.createHash('md4')&lt;/code&gt; to fingerprint chunk content. On Node.js 18+, OpenSSL 3 refuses that call and throws &lt;code&gt;ERR_OSSL_EVP_UNSUPPORTED&lt;/code&gt;, which surfaces as the &lt;code&gt;0308010C&lt;/code&gt; error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Lambda teams hit this at runtime-upgrade time
&lt;/h2&gt;

&lt;p&gt;The error lives in your &lt;strong&gt;build step&lt;/strong&gt;, not inside the Lambda execution environment. The two are linked because of the deprecation schedule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nodejs16.x&lt;/code&gt; — the last Lambda runtime on OpenSSL 1.1 — is on the deprecation path. Teams moving to &lt;code&gt;nodejs18.x&lt;/code&gt; or &lt;code&gt;nodejs22.x&lt;/code&gt; naturally update their CI Node version to match.&lt;/li&gt;
&lt;li&gt;The Lambda runtime itself runs your handler fine. OpenSSL 3 does not break ES modules, &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;, or standard crypto like AES-256-GCM or SHA-256.&lt;/li&gt;
&lt;li&gt;It breaks &lt;strong&gt;build tooling calling &lt;code&gt;createHash('md4')&lt;/code&gt;&lt;/strong&gt; — tooling that runs on your CI machine, not inside Lambda. The runtime upgrade triggers the CI upgrade, which triggers the build failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which Node.js version ships which OpenSSL:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lambda runtime&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;OpenSSL&lt;/th&gt;
&lt;th&gt;&lt;code&gt;createHash('md4')&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;nodejs16.x&lt;/td&gt;
&lt;td&gt;16.x&lt;/td&gt;
&lt;td&gt;1.1.1&lt;/td&gt;
&lt;td&gt;Works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nodejs18.x&lt;/td&gt;
&lt;td&gt;18.x&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;Fails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nodejs20.x&lt;/td&gt;
&lt;td&gt;20.x&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;Fails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;nodejs22.x&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;22.x&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fails&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Fix 1 — upgrade webpack or react-scripts (durable)
&lt;/h2&gt;

&lt;p&gt;Webpack 5 replaced the MD4 call with its own pure-JavaScript xxhash64 implementation that does not touch OpenSSL at all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# webpack-only project&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; webpack@5 webpack-cli@5

&lt;span class="c"&gt;# Create React App / react-scripts&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; react-scripts@5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you cannot upgrade webpack itself, override the hash function in &lt;code&gt;webpack.config.js&lt;/code&gt;:&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;hashFunction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SHA-256 is in OpenSSL 3's default provider, so this works on all supported Node.js versions without any environment variable changes.&lt;/p&gt;

&lt;p&gt;For projects using &lt;strong&gt;Jest&lt;/strong&gt;, the MD4 call was removed from &lt;code&gt;jest-haste-map&lt;/code&gt; in 27.4.2. Upgrade your Jest version if the trace points there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 2 — re-enable the legacy provider (stopgap only)
&lt;/h2&gt;

&lt;p&gt;If you cannot touch the tooling today, set &lt;code&gt;NODE_OPTIONS&lt;/code&gt; before running your build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env / CI environment variable&lt;/span&gt;
&lt;span class="nv"&gt;NODE_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;--openssl-legacy-provider&lt;/span&gt;

&lt;span class="c"&gt;# Or inline in package.json scripts&lt;/span&gt;
&lt;span class="s2"&gt;"build"&lt;/span&gt;: &lt;span class="s2"&gt;"NODE_OPTIONS=--openssl-legacy-provider react-scripts build"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a Dockerfile building a Lambda deployment package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nv"&gt;NODE_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;--openssl-legacy-provider&lt;/span&gt; npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Do not leave this in place permanently.&lt;/strong&gt; The flag re-enables deprecated algorithms across the entire Node.js process. It is also subject to removal in a future OpenSSL release, meaning it will silently stop working and break the build again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confirm no legacy crypto calls remain
&lt;/h2&gt;

&lt;p&gt;After the fix, verify clean with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Should print nothing OpenSSL-related&lt;/span&gt;
node &lt;span class="nt"&gt;--trace-deprecation&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"const w = require('webpack'); w({}, () =&amp;gt; {})"&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; openssl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the Lambda runtime version you are targeting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda get-function-configuration &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; &amp;lt;your-function-name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; Runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The pattern to internalize
&lt;/h2&gt;

&lt;p&gt;This error is not a crypto vulnerability — it is a dependency age signal. Webpack 4 and react-scripts 4 were released in 2020. The projects that hit this error in 2026 are the same ones that will hit &lt;code&gt;node-module-version-mismatch&lt;/code&gt; (native addons), &lt;code&gt;Cannot find module 'aws-sdk'&lt;/code&gt; (SDK v2 removal), and &lt;code&gt;crypto.createCipher is not a function&lt;/code&gt; (removed in Node.js 22). An OpenSSL 3 error is a useful proxy for "this build pipeline has not been reviewed since the nodejs16.x era."&lt;/p&gt;

&lt;p&gt;Fix the hash function, then audit the rest of the dependency tree before your next Lambda runtime deadline.&lt;/p&gt;




&lt;p&gt;Not sure which of your Lambda functions are still on deprecated runtimes or blocked SDKs? &lt;a href="https://eolkits.com/scan" rel="noopener noreferrer"&gt;Run a free EOLkits scan&lt;/a&gt; — it maps every function to its runtime deprecation date and flags the issues before AWS does.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>"Error: Cannot find module 'aws-sdk'" on Lambda — migrating to @aws-sdk v3</title>
      <dc:creator>ntoledo319</dc:creator>
      <pubDate>Mon, 06 Jul 2026 07:17:03 +0000</pubDate>
      <link>https://dev.to/ntoledo319/error-cannot-find-module-aws-sdk-on-lambda-migrating-to-aws-sdk-v3-2n9k</link>
      <guid>https://dev.to/ntoledo319/error-cannot-find-module-aws-sdk-on-lambda-migrating-to-aws-sdk-v3-2n9k</guid>
      <description>&lt;p&gt;If you upgraded a Lambda function from &lt;code&gt;nodejs16.x&lt;/code&gt; to &lt;code&gt;nodejs18.x&lt;/code&gt; (or &lt;code&gt;nodejs20.x&lt;/code&gt; / &lt;code&gt;nodejs22.x&lt;/code&gt;) and your logs now show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Runtime.ImportModuleError: Error: Cannot find module 'aws-sdk'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you're not missing a locally installed package. AWS deliberately stopped bundling it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this happens
&lt;/h2&gt;

&lt;p&gt;Until &lt;code&gt;nodejs16.x&lt;/code&gt;, Lambda preinstalled &lt;strong&gt;aws-sdk v2&lt;/strong&gt; (&lt;code&gt;require('aws-sdk')&lt;/code&gt;) in every Node.js runtime. It was free — zero deployment overhead, no &lt;code&gt;package.json&lt;/code&gt; entry needed.&lt;/p&gt;

&lt;p&gt;From &lt;strong&gt;&lt;code&gt;nodejs18.x&lt;/code&gt; onwards&lt;/strong&gt; AWS replaced it: only &lt;strong&gt;AWS SDK for JavaScript v3&lt;/strong&gt; (the &lt;code&gt;@aws-sdk/*&lt;/code&gt; modular packages) is bundled. The monolithic &lt;code&gt;aws-sdk&lt;/code&gt; v2 package is gone from the runtime environment entirely.&lt;/p&gt;

&lt;p&gt;There is a second reason not to reach for the "just bundle v2" escape hatch: aws-sdk v2 reached &lt;strong&gt;end-of-support on September 8, 2025&lt;/strong&gt; and no longer receives security patches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix A — Migrate to @aws-sdk v3 (durable)
&lt;/h2&gt;

&lt;p&gt;v3 is modular: instead of one ~75 MB monolith, you install only the services you need. Each service lives in its own package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (v2 — S3):&lt;/strong&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AWS&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="s1"&gt;aws-sdk&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;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;S3&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-east-1&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getObject&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-bucket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (v3 — S3):&lt;/strong&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GetObjectCommand&lt;/span&gt; &lt;span class="p"&gt;}&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="s1"&gt;@aws-sdk/client-s3&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;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-east-1&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GetObjectCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-bucket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file.json&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;Three things change in every service:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import the specific &lt;strong&gt;Client&lt;/strong&gt; and &lt;strong&gt;Command&lt;/strong&gt; classes from &lt;code&gt;@aws-sdk/client-&amp;lt;service&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Wrap parameters in a &lt;strong&gt;Command&lt;/strong&gt; object and pass it to &lt;code&gt;client.send(...)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Drop &lt;code&gt;.promise()&lt;/code&gt; — v3 returns native promises directly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;DynamoDB DocumentClient (before / after):&lt;/strong&gt;&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;// v2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DynamoDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DocumentClient&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;doc&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="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&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="nf"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// v3&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DynamoDBClient&lt;/span&gt; &lt;span class="p"&gt;}&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="s1"&gt;@aws-sdk/client-dynamodb&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DynamoDBDocumentClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GetCommand&lt;/span&gt; &lt;span class="p"&gt;}&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="s1"&gt;@aws-sdk/lib-dynamodb&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DynamoDBDocumentClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DynamoDBClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-east-1&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GetCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For DynamoDB, &lt;code&gt;@aws-sdk/lib-dynamodb&lt;/code&gt; is the high-level v3 equivalent of &lt;code&gt;DocumentClient&lt;/code&gt;. It marshals/unmarshals attribute types, so the call-site feels similar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automate the mechanical rewrites with codemod
&lt;/h3&gt;

&lt;p&gt;AWS ships a codemod that handles most of the straightforward conversions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; aws-sdk-js-codemod

&lt;span class="c"&gt;# Single file&lt;/span&gt;
npx aws-sdk-js-codemod &lt;span class="nt"&gt;-t&lt;/span&gt; v2-to-v3 src/handler.js

&lt;span class="c"&gt;# Whole project&lt;/span&gt;
npx aws-sdk-js-codemod &lt;span class="nt"&gt;-t&lt;/span&gt; v2-to-v3 &lt;span class="s1"&gt;'src/**/*.js'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The codemod is reliable on simple patterns. Review the diff: dynamic service selection, callback-style calls, and chained middleware usually need manual cleanup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix B — Bundle aws-sdk v2 in your package (stopgap only)
&lt;/h2&gt;

&lt;p&gt;If you cannot migrate immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws-sdk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.1692.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Include &lt;code&gt;node_modules&lt;/code&gt; in your deployment ZIP or a Lambda layer. This unblocks deploys but adds ~25 MB of cold-start weight and leaves your functions on an end-of-support library. Treat it as a bridge, not a destination.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if the error comes from a dependency, not your code?
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;npm ls aws-sdk&lt;/code&gt; to find who imports it transitively. Most major packages (Amplify, CDK custom resources, Middy middleware) have published v3-compatible versions — upgrade first. If no upgrade exists, Fix B applies at the layer level until an upstream fix lands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scan before you flip the runtime
&lt;/h2&gt;

&lt;p&gt;Before changing &lt;code&gt;nodejs16.x&lt;/code&gt; → &lt;code&gt;nodejs18.x&lt;/code&gt; across your stack, find every v2 import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"require('aws-sdk')&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;require(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;aws-sdk&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;from 'aws-sdk'"&lt;/span&gt; src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any hit needs to be migrated or bundled before the runtime label changes, or the function will fail its first invocation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundler gotcha: esbuild 0.22+
&lt;/h2&gt;

&lt;p&gt;If you use esbuild to package your functions (SAM's default from v1.x), note that esbuild 0.22+ changed its default to treat &lt;code&gt;node_modules&lt;/code&gt; as external — meaning even if you add &lt;code&gt;aws-sdk&lt;/code&gt; to &lt;code&gt;package.json&lt;/code&gt;, esbuild may exclude it from the ZIP. Force bundling:&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="c1"&gt;# SAM template.yaml&lt;/span&gt;
&lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;BuildMethod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;esbuild&lt;/span&gt;
  &lt;span class="na"&gt;BuildProperties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bundle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with the CLI flag: &lt;code&gt;esbuild --packages=bundle&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;Every deprecated Lambda runtime across your account — including every function still wired to &lt;code&gt;nodejs16.x&lt;/code&gt; — shows up in a free EOLkits scan. Run it before the next deploy, not after: &lt;strong&gt;&lt;a href="https://eolkits.com/scan" rel="noopener noreferrer"&gt;eolkits.com/scan&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Python 3.13 on AWS Lambda — cgi, telnetlib, crypt, lib2to3 removed (PEP 594)</title>
      <dc:creator>ntoledo319</dc:creator>
      <pubDate>Mon, 29 Jun 2026 07:17:03 +0000</pubDate>
      <link>https://dev.to/ntoledo319/python-313-on-aws-lambda-cgi-telnetlib-crypt-lib2to3-removed-pep-594-2h67</link>
      <guid>https://dev.to/ntoledo319/python-313-on-aws-lambda-cgi-telnetlib-crypt-lib2to3-removed-pep-594-2h67</guid>
      <description>&lt;p&gt;AWS Lambda launched the &lt;code&gt;python3.13&lt;/code&gt; runtime in November 2024 — Amazon Linux 2023, Python 3.13.x, LTS support through October 2029. If you're still on &lt;code&gt;python3.9&lt;/code&gt; or &lt;code&gt;python3.10&lt;/code&gt;, the create-block deadline hits &lt;strong&gt;2027-02-01&lt;/strong&gt;; &lt;code&gt;python3.11&lt;/code&gt; create-blocks at &lt;strong&gt;2027-07-31&lt;/strong&gt;. Many teams are jumping straight to &lt;code&gt;python3.13&lt;/code&gt; to bank the longest runway.&lt;/p&gt;

&lt;p&gt;What bites them isn't the runtime label change. It's &lt;strong&gt;PEP 594&lt;/strong&gt; — the "dead batteries" cleanup that deprecated 19 stdlib modules in Python 3.11 (warnings only) and &lt;strong&gt;deleted all of them in Python 3.13&lt;/strong&gt;. Cold start, hard crash, &lt;code&gt;ModuleNotFoundError&lt;/code&gt;. Here are the four that actually appear in Lambda functions and their transitive dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;ModuleNotFoundError: No module named 'cgi'&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;cgi&lt;/code&gt; and &lt;code&gt;cgitb&lt;/code&gt; modules are gone in Python 3.13.&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;# Breaks on python3.13
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cgi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parse_qs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FieldStorage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;escape&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cgitb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;cgitb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cgi.parse_qs&lt;/code&gt; / &lt;code&gt;cgi.parse_qsl&lt;/code&gt; → &lt;code&gt;urllib.parse.parse_qs&lt;/code&gt; / &lt;code&gt;urllib.parse.parse_qsl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cgi.escape&lt;/code&gt; → &lt;code&gt;html.escape&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Multipart form parsing (&lt;code&gt;FieldStorage&lt;/code&gt;) → &lt;code&gt;multipart&lt;/code&gt; library, or your framework's built-in (&lt;code&gt;werkzeug.formparser&lt;/code&gt;, &lt;code&gt;starlette.requests.Request.form()&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Drop &lt;code&gt;cgitb.enable()&lt;/code&gt; — use structured logging (&lt;code&gt;logging.exception&lt;/code&gt;) instead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most common place this surfaces in Lambda is a dependency that still imports &lt;code&gt;cgi&lt;/code&gt; for query-string parsing — &lt;code&gt;pip show -f &amp;lt;package&amp;gt;&lt;/code&gt; to locate it, then upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;ModuleNotFoundError: No module named 'telnetlib'&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;telnetlib&lt;/span&gt;  &lt;span class="c1"&gt;# removed in Python 3.13
&lt;/span&gt;&lt;span class="n"&gt;tn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;telnetlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Telnet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Network/device automation:&lt;/strong&gt; replace with &lt;a href="https://pypi.org/project/telnetlib3/" rel="noopener noreferrer"&gt;&lt;code&gt;telnetlib3&lt;/code&gt;&lt;/a&gt; (asyncio-native, maintained) or &lt;code&gt;Exscript&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better:&lt;/strong&gt; switch to SSH where the device supports it — &lt;code&gt;paramiko&lt;/code&gt; or &lt;code&gt;netmiko&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pinning to &lt;code&gt;python3.12&lt;/code&gt; still includes &lt;code&gt;telnetlib&lt;/code&gt;, but &lt;code&gt;python3.12&lt;/code&gt; itself will eventually deprecate — treat that as a stopgap, not a fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;ModuleNotFoundError: No module named 'crypt'&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The Unix password-hashing module was removed because its underlying algorithms (DES-crypt, MD5-crypt) are cryptographically broken and belong nowhere near new code.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;crypt&lt;/span&gt;
&lt;span class="n"&gt;hashed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mksalt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;METHOD_SHA512&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New password hashing:&lt;/strong&gt; &lt;code&gt;passlib&lt;/code&gt; (&lt;code&gt;bcrypt&lt;/code&gt;, &lt;code&gt;argon2-cffi&lt;/code&gt;) or &lt;code&gt;hashlib.scrypt&lt;/code&gt; / &lt;code&gt;hashlib.pbkdf2_hmac&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify existing &lt;code&gt;crypt(3)&lt;/code&gt; hashes:&lt;/strong&gt; &lt;code&gt;passlib.hash.sha512_crypt.verify(password, stored_hash)&lt;/code&gt; — it implements the same crypt(3) schemes so you can verify old hashes during a migration window.&lt;/li&gt;
&lt;li&gt;There is no stdlib drop-in replacement. Don't reach for &lt;code&gt;hashlib.md5&lt;/code&gt; — that's not a password hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This one shows up most often in provisioning scripts and user-management Lambda functions inherited from old EC2 tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;ModuleNotFoundError: No module named 'lib2to3'&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lib2to3&lt;/code&gt; (and the &lt;code&gt;2to3&lt;/code&gt; command-line tool) were removed because the internal grammar couldn't track new Python syntax — it was itself becoming obsolete.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;lib2to3&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pygram&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pytree&lt;/span&gt;  &lt;span class="c1"&gt;# gone in Python 3.13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code parsing/transformation: &lt;a href="https://libcst.readthedocs.io/" rel="noopener noreferrer"&gt;&lt;code&gt;LibCST&lt;/code&gt;&lt;/a&gt; or &lt;code&gt;parso&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If this comes from a dependency (build tools, older linters, &lt;code&gt;black &amp;lt; 24&lt;/code&gt;), upgrade it — modern versions have already removed the &lt;code&gt;lib2to3&lt;/code&gt; dependency.&lt;/li&gt;
&lt;li&gt;For a one-off Python 2→3 migration: run &lt;code&gt;2to3&lt;/code&gt; from a Python ≤ 3.12 environment before upgrading the runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Grep your dependencies before deploying
&lt;/h2&gt;

&lt;p&gt;PEP 594 removed 19 modules in total. The four above are the ones that appear in Lambda workloads, but also removed were: &lt;code&gt;aifc&lt;/code&gt;, &lt;code&gt;audioop&lt;/code&gt;, &lt;code&gt;chunk&lt;/code&gt;, &lt;code&gt;cgitb&lt;/code&gt;, &lt;code&gt;imghdr&lt;/code&gt;, &lt;code&gt;mailcap&lt;/code&gt;, &lt;code&gt;msilib&lt;/code&gt;, &lt;code&gt;nis&lt;/code&gt;, &lt;code&gt;nntplib&lt;/code&gt;, &lt;code&gt;ossaudiodev&lt;/code&gt;, &lt;code&gt;pipes&lt;/code&gt;, &lt;code&gt;sndhdr&lt;/code&gt;, &lt;code&gt;spwd&lt;/code&gt;, &lt;code&gt;sunau&lt;/code&gt;, &lt;code&gt;uu&lt;/code&gt;, &lt;code&gt;xdrlib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A quick scan before you flip the runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run from your virtualenv or package directory&lt;/span&gt;
python3.13 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"
import importlib, sys
dead = ['cgi','cgitb','telnetlib','crypt','lib2to3','aifc','audioop',
        'chunk','imghdr','mailcap','nis','nntplib','ossaudiodev',
        'pipes','sndhdr','sunau','uu','xdrlib']
for m in dead:
    try:
        importlib.import_module(m)
        print(f'WARN: {m} somehow importable')
    except ModuleNotFoundError:
        pass
print('Scan complete')
"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better yet, test your handler locally on a Python 3.13 environment before deploying to Lambda. The errors above are cold-start killers — they won't appear until the function is invoked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeline recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runtime&lt;/th&gt;
&lt;th&gt;Deprecated&lt;/th&gt;
&lt;th&gt;Create blocked&lt;/th&gt;
&lt;th&gt;Update blocked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python3.9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2025-12-15&lt;/td&gt;
&lt;td&gt;2027-02-01&lt;/td&gt;
&lt;td&gt;2027-03-03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python3.10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2026-03-31&lt;/td&gt;
&lt;td&gt;2027-02-01&lt;/td&gt;
&lt;td&gt;2027-03-03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python3.11&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2027-06-30&lt;/td&gt;
&lt;td&gt;2027-07-31&lt;/td&gt;
&lt;td&gt;2027-08-31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python3.12&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;not yet deprecated&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;python3.13&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;not yet deprecated&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sources: &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html" rel="noopener noreferrer"&gt;AWS Lambda runtime deprecation table&lt;/a&gt;, &lt;a href="https://docs.python.org/3/whatsnew/3.13.html" rel="noopener noreferrer"&gt;Python 3.13 What's New&lt;/a&gt;, &lt;a href="https://peps.python.org/pep-0594/" rel="noopener noreferrer"&gt;PEP 594&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;The free &lt;strong&gt;&lt;a href="https://eolkits.com/scan" rel="noopener noreferrer"&gt;EOLkits scanner&lt;/a&gt;&lt;/strong&gt; detects deprecated Lambda runtimes and flags known packages that still import the removed modules — in your browser, nothing uploaded. Full per-error fixes and the migration deadline timeline: &lt;strong&gt;&lt;a href="https://eolkits.com/migrate/lambda-python-3.11-eol/" rel="noopener noreferrer"&gt;eolkits.com/migrate/lambda-python-3.11-eol&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>lambda</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Python 3.12 on AWS Lambda — distutils, imp, and collections are gone</title>
      <dc:creator>ntoledo319</dc:creator>
      <pubDate>Tue, 23 Jun 2026 07:17:03 +0000</pubDate>
      <link>https://dev.to/ntoledo319/python-312-on-aws-lambda-distutils-imp-and-collections-are-gone-6ac</link>
      <guid>https://dev.to/ntoledo319/python-312-on-aws-lambda-distutils-imp-and-collections-are-gone-6ac</guid>
      <description>&lt;p&gt;AWS Lambda's &lt;code&gt;python3.9&lt;/code&gt;, &lt;code&gt;3.10&lt;/code&gt;, and &lt;code&gt;3.11&lt;/code&gt; runtimes are on the deprecation track; &lt;code&gt;python3.12&lt;/code&gt; (on Amazon Linux 2023) is the target. The runtime swap is one line — but Python 3.12 itself removed a pile of long-deprecated stdlib, so code that ran on 3.9 throws on import.&lt;/p&gt;

&lt;h2&gt;
  
  
  The removals you'll hit
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ModuleNotFoundError: No module named 'distutils'&lt;/code&gt;&lt;/strong&gt; — removed in 3.12 (PEP 632). Replace with &lt;code&gt;setuptools&lt;/code&gt; + &lt;code&gt;packaging&lt;/code&gt; (e.g. &lt;code&gt;packaging.version.Version&lt;/code&gt; instead of &lt;code&gt;distutils.version.LooseVersion&lt;/code&gt;). Interim: &lt;code&gt;pip install 'setuptools&amp;lt;81'&lt;/code&gt; (still vendors a shim).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ModuleNotFoundError: No module named 'imp'&lt;/code&gt;&lt;/strong&gt; — removed in 3.12. Use &lt;code&gt;importlib&lt;/code&gt; (&lt;code&gt;importlib.util.find_spec&lt;/code&gt;, &lt;code&gt;import_module&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;AttributeError: module 'collections' has no attribute 'Mapping'&lt;/code&gt;&lt;/strong&gt; — the ABCs moved to &lt;code&gt;collections.abc&lt;/code&gt; (removed from &lt;code&gt;collections&lt;/code&gt; in 3.10). &lt;code&gt;from collections.abc import Mapping&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;DeprecationWarning: datetime.datetime.utcnow() is deprecated&lt;/code&gt;&lt;/strong&gt; — use &lt;code&gt;datetime.now(datetime.timezone.utc)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one that isn't in your code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/lib64/libc.so.6: version `GLIBC_2.28' not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Native wheels (cryptography, numpy, pydantic-core…) link against the glibc of the box that built them. AL2 runtimes ship glibc 2.26; AL2023 (python3.12) ships 2.34. Build for the target: &lt;code&gt;pip install --platform manylinux2014_x86_64 --only-binary=:all: --target ./package &amp;lt;pkg&amp;gt;&lt;/code&gt;, or build inside &lt;code&gt;public.ecr.aws/lambda/python:3.12&lt;/code&gt;. Match the arch (x86_64 vs arm64) too.&lt;/p&gt;

&lt;h2&gt;
  
  
  When AWS blocks you
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The runtime parameter of python3.9 is no longer supported for creating or updating AWS Lambda functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the block date. Set &lt;code&gt;Runtime: python3.12&lt;/code&gt; (SAM/CFN), &lt;code&gt;lambda.Runtime.PYTHON_3_12&lt;/code&gt; (CDK), or &lt;code&gt;runtime = "python3.12"&lt;/code&gt; (Terraform), fix the imports above, redeploy.&lt;/p&gt;




&lt;p&gt;The free &lt;strong&gt;&lt;a href="https://eolkits.com/scan" rel="noopener noreferrer"&gt;EOLkits scanner&lt;/a&gt;&lt;/strong&gt; flags every deprecated runtime and the dependency breaks above from your &lt;code&gt;requirements.txt&lt;/code&gt; / &lt;code&gt;pyproject.toml&lt;/code&gt; / IaC — in your browser, nothing uploaded. There's an MIT CLI (&lt;code&gt;python-pivot&lt;/code&gt;) that codemods most of it, and a hash-anchored audit if you want it scored and done for you.&lt;/p&gt;

&lt;p&gt;Cited deadlines + per-error fixes: &lt;strong&gt;&lt;a href="https://eolkits.com/migrate/" rel="noopener noreferrer"&gt;eolkits.com/migrate&lt;/a&gt;&lt;/strong&gt; · &lt;strong&gt;&lt;a href="https://eolkits.com/fix/" rel="noopener noreferrer"&gt;eolkits.com/fix&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>python</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Migrating AWS Lambda from Node.js 20 to 22 — every breaking change</title>
      <dc:creator>ntoledo319</dc:creator>
      <pubDate>Mon, 22 Jun 2026 21:11:30 +0000</pubDate>
      <link>https://dev.to/ntoledo319/migrating-aws-lambda-from-nodejs-20-to-22-every-breaking-change-8cp</link>
      <guid>https://dev.to/ntoledo319/migrating-aws-lambda-from-nodejs-20-to-22-every-breaking-change-8cp</guid>
      <description>&lt;p&gt;AWS deprecates Lambda runtimes on a 3-phase schedule: Phase 1 ends security patches, Phase 2 blocks &lt;strong&gt;creating&lt;/strong&gt; new functions, Phase 3 blocks &lt;strong&gt;updating&lt;/strong&gt; existing ones. Once Phase 3 hits, a frozen function's only path forward is a full redeploy on a new runtime. &lt;code&gt;nodejs20.x&lt;/code&gt; is on that track; &lt;code&gt;nodejs22.x&lt;/code&gt; is the target (LTS, maintained into 2027).&lt;/p&gt;

&lt;p&gt;Most code moves cleanly. Here's the set that doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;code&gt;aws-sdk&lt;/code&gt; v2 is no longer bundled
&lt;/h2&gt;

&lt;p&gt;On &lt;code&gt;nodejs16.x&lt;/code&gt; and earlier, AWS preinstalled the v2 SDK. From &lt;code&gt;nodejs18.x&lt;/code&gt; onward, only &lt;strong&gt;v3&lt;/strong&gt; (&lt;code&gt;@aws-sdk/*&lt;/code&gt;) is bundled. So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Cannot find module 'aws-sdk'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix: migrate to modular v3 clients, e.g. &lt;code&gt;const { S3Client } = require('@aws-sdk/client-s3')&lt;/code&gt;. v3 also returns promises directly (no &lt;code&gt;.promise()&lt;/code&gt;), and response shapes differ. Quick unblock: bundle &lt;code&gt;aws-sdk&lt;/code&gt; in your package (adds cold-start weight).&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Import assertions → import attributes
&lt;/h2&gt;

&lt;p&gt;Node 22 ships the finalized spec, which renamed &lt;code&gt;assert&lt;/code&gt; to &lt;code&gt;with&lt;/code&gt;:&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;// Node 20 (valid)  -&amp;gt; Node 22 (broken)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// Node 22 (valid)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cfg&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&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;h2&gt;
  
  
  3. Native addons must be rebuilt
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: The module was compiled against a different Node.js version using NODE_MODULE_VERSION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Native modules (sharp, bcrypt, better-sqlite3…) are tied to the Node ABI. Rebuild on the target version, or bump to a release with a Node 22 prebuild. Dead packages (node-sass, fibers) must be replaced.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. OpenSSL 3
&lt;/h2&gt;

&lt;p&gt;Node 17+ ships OpenSSL 3, which rejects legacy hashing some older tooling relies on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: error:0308010C:digital envelope routines::unsupported
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix: upgrade the tool (webpack 5, react-scripts 5+). &lt;code&gt;--openssl-legacy-provider&lt;/code&gt; is a stopgap only.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;crypto.createCipher&lt;/code&gt; removed
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;crypto.createCipher&lt;/code&gt; / &lt;code&gt;createDecipher&lt;/code&gt; were removed in Node 22 — switch to &lt;code&gt;createCipheriv&lt;/code&gt; with an explicit key + IV (&lt;code&gt;scrypt&lt;/code&gt;/&lt;code&gt;pbkdf2&lt;/code&gt; + &lt;code&gt;randomBytes&lt;/code&gt;).&lt;/p&gt;




&lt;p&gt;I wrote an open-source CLI (&lt;code&gt;lambda-lifeline&lt;/code&gt;) that scans for all of these, codemods what's mechanical, patches your IaC, and stages a canary with rollback — plus a &lt;strong&gt;free browser scanner&lt;/strong&gt; that flags them in your config in ~30 seconds, nothing uploaded: &lt;strong&gt;&lt;a href="https://eolkits.com/scan" rel="noopener noreferrer"&gt;eolkits.com/scan&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Full guide with every case + captured output: &lt;strong&gt;&lt;a href="https://eolkits.com/blog/migrating-lambda-nodejs-20-to-22/" rel="noopener noreferrer"&gt;eolkits.com/blog/migrating-lambda-nodejs-20-to-22&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>node</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Amazon Linux 2 is EOL on June 30, 2026 — here's everything that breaks</title>
      <dc:creator>ntoledo319</dc:creator>
      <pubDate>Mon, 22 Jun 2026 21:10:09 +0000</pubDate>
      <link>https://dev.to/ntoledo319/amazon-linux-2-is-eol-on-june-30-2026-heres-everything-that-breaks-3end</link>
      <guid>https://dev.to/ntoledo319/amazon-linux-2-is-eol-on-june-30-2026-heres-everything-that-breaks-3end</guid>
      <description>&lt;p&gt;Amazon Linux 2 reaches &lt;strong&gt;end of life on June 30, 2026&lt;/strong&gt;. After that: no security patches, no new AMIs, no extras updates. Anything still pinned to AL2 in a launch template, EKS node group, ECS task, Beanstalk platform, or container base image is running unpatched from that day on.&lt;/p&gt;

&lt;p&gt;Here's what actually changes when you move to Amazon Linux 2023 — the stuff that breaks boot scripts and CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes on AL2023
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Amazon Linux 2&lt;/th&gt;
&lt;th&gt;Amazon Linux 2023&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Package manager&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;dnf&lt;/code&gt; (a &lt;code&gt;yum&lt;/code&gt; symlink remains)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extras&lt;/td&gt;
&lt;td&gt;&lt;code&gt;amazon-linux-extras&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;removed&lt;/strong&gt; — packages are default, version-namespaced (&lt;code&gt;python3.11&lt;/code&gt;, &lt;code&gt;nginx1.24&lt;/code&gt;), or in SPAL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time sync&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ntpd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;chronyd&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firewall&lt;/td&gt;
&lt;td&gt;&lt;code&gt;iptables&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nftables&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;2.7 and 3.x&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.x only — no Python 2&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;glibc&lt;/td&gt;
&lt;td&gt;2.26&lt;/td&gt;
&lt;td&gt;2.34&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The errors you'll hit (and the fix)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;amazon-linux-extras: command not found&lt;/code&gt;&lt;/strong&gt; — it doesn't exist on AL2023. Install directly with &lt;code&gt;dnf&lt;/code&gt;, version-namespaced, or via SPAL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Failed to start ntpd.service: Unit ntpd.service not found&lt;/code&gt;&lt;/strong&gt; — use &lt;code&gt;chronyd&lt;/code&gt; instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/usr/bin/env: 'python2': No such file or directory&lt;/code&gt;&lt;/strong&gt; — there's no Python 2; port the script to &lt;code&gt;python3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Error: Unable to find a match: &amp;lt;package&amp;gt;&lt;/code&gt;&lt;/strong&gt; — the package was renamed/version-namespaced/moved to SPAL. &lt;code&gt;dnf search&lt;/code&gt; for the real name.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The migration checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Inventory&lt;/strong&gt; every AL2 AMI, launch template, EKS node group, ECS task, Beanstalk platform, and container base image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebuild the base AMI&lt;/strong&gt; on AL2023 (Packer / EC2 Image Builder).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package manager&lt;/strong&gt;: move &lt;code&gt;yum&lt;/code&gt; usage to &lt;code&gt;dnf&lt;/code&gt;, drop &lt;code&gt;amazon-linux-extras&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Services&lt;/strong&gt;: &lt;code&gt;ntpd&lt;/code&gt; → &lt;code&gt;chronyd&lt;/code&gt;, &lt;code&gt;iptables&lt;/code&gt; → &lt;code&gt;nftables&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt;: port &lt;code&gt;python2&lt;/code&gt; scripts/shebangs to &lt;code&gt;python3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test&lt;/strong&gt; boot, app start, networking, and time sync on a canary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Roll out&lt;/strong&gt; staged (5 → 25 → 50 → 100%) with a tested rollback.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;I got tired of grepping for this by hand, so I built a &lt;strong&gt;free scanner&lt;/strong&gt; — drop your Terraform / CloudFormation / Packer / Ansible into the browser and it flags every AL2 reference and the errors above, with the AWS source for each. Nothing is uploaded. &lt;strong&gt;&lt;a href="https://eolkits.com/scan" rel="noopener noreferrer"&gt;Try it free → eolkits.com/scan&lt;/a&gt;&lt;/strong&gt;. There's also an MIT CLI that does the codemods, and a paid audit if you want it done for you.&lt;/p&gt;

&lt;p&gt;Full checklist with the per-error fixes: &lt;strong&gt;&lt;a href="https://eolkits.com/amazon-linux-2-eol-checklist/" rel="noopener noreferrer"&gt;eolkits.com/amazon-linux-2-eol-checklist&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>linux</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
