<?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: M. Abdullah Bin Aftab</title>
    <description>The latest articles on DEV Community by M. Abdullah Bin Aftab (@heighter).</description>
    <link>https://dev.to/heighter</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%2F1276763%2F8516c785-2ecf-4b28-ac6a-a96156980c01.png</url>
      <title>DEV Community: M. Abdullah Bin Aftab</title>
      <link>https://dev.to/heighter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heighter"/>
    <language>en</language>
    <item>
      <title>Building Distributed Tracing for a Data-Intensive Platform: The X-Ray Journey on AWS</title>
      <dc:creator>M. Abdullah Bin Aftab</dc:creator>
      <pubDate>Fri, 10 Jul 2026 06:27:21 +0000</pubDate>
      <link>https://dev.to/heighter/building-distributed-tracing-for-a-data-intensive-platform-the-x-ray-journey-on-aws-3dpi</link>
      <guid>https://dev.to/heighter/building-distributed-tracing-for-a-data-intensive-platform-the-x-ray-journey-on-aws-3dpi</guid>
      <description>&lt;h2&gt;
  
  
  The Problem We Started With
&lt;/h2&gt;

&lt;p&gt;Our donation platform runs on 50+ AWS Lambda functions, handling everything from &lt;strong&gt;Stripe/PayPal&lt;/strong&gt; payments to &lt;strong&gt;DB&lt;/strong&gt; writes to SQS-based background processing (queue consolidation, tax receipts, user events, and more). When something went wrong in production, we had no easy way to answer basic questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which specific function failed, and why?&lt;/li&gt;
&lt;li&gt;Did a donation actually reach MongoDB, or did it fail silently?&lt;/li&gt;
&lt;li&gt;When a webhook queues a background job, does that job actually run, and how long does the whole chain take?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We needed &lt;strong&gt;distributed tracing&lt;/strong&gt;: a way to see, end-to-end, what happens when a request flows through our system. &lt;strong&gt;AWS X-Ray&lt;/strong&gt; is the natural tool for this on &lt;strong&gt;Lambda&lt;/strong&gt;. This is the story of getting it working, including the two hardest problems we hit: &lt;strong&gt;"Unknown Host" nodes&lt;/strong&gt; polluting every trace, and &lt;strong&gt;SQS producer→consumer visibility&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt #1: ADOT (OpenTelemetry) - The Modern Path That Wasn't Ready
&lt;/h2&gt;

&lt;p&gt;AWS's recommended modern approach for Lambda tracing is the ADOT (AWS Distro for OpenTelemetry) Lambda layer. It auto-instruments HTTP, AWS SDK calls, and more, with zero code changes, attach a layer and set an environment variable.&lt;/p&gt;

&lt;p&gt;We attached it. Every function immediately started crashing on cold start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Runtime.CallbackHandlerDeprecated: AWS Lambda has removed support for
callback-based function handlers starting with Node.js 24.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Investigation confirmed this wasn't a config mistake, it's a real, unresolved AWS limitation. Node.js 24 dropped support for callback-style Lambda handlers, and ADOT's Node.js wrapper hasn't been updated to reflect this change. I found open &lt;strong&gt;GitHub&lt;/strong&gt; issues on &lt;code&gt;aws-observability/aws-otel-lambda&lt;/code&gt; from other teams hitting the same wall, with no fix timeline from AWS. Their own docs list Node 22 as the latest officially supported runtime for ADOT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decision:&lt;/strong&gt; stick with Node.js 24 (rather than downgrade) and use the classic &lt;strong&gt;AWS X-Ray SDK&lt;/strong&gt; (via AWS Lambda Powertools' &lt;code&gt;Tracer&lt;/code&gt;) instead. Less automatic, but stable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt #2: Powertools Tracer, Getting the Basics Right
&lt;/h2&gt;

&lt;p&gt;We rebuilt tracing using &lt;code&gt;@aws-lambda-powertools/tracer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracer&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;Tracer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;XYZ&amp;gt;_Backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withMetrics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handlerLogic&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;segment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSegment&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;subsegment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;segment&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;addNewSubsegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;handlerLogic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;addError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;close&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every one of our &lt;strong&gt;~50+&lt;/strong&gt; Lambda handlers got wrapped with &lt;code&gt;withMetrics&lt;/code&gt;, giving each function its own named trace with duration and error status. Combined with enabling &lt;code&gt;tracingConfig: { mode: "Active" }&lt;/code&gt; on every function in our CDK backend definition, this gave us basic, working, per-function tracing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem #1: "Unknown Host"
&lt;/h2&gt;

&lt;p&gt;Once external calls (MongoDB, Stripe, PayPal) started happening inside these traced functions, X-Ray started showing a strange red node labeled &lt;strong&gt;"Unknown host"&lt;/strong&gt; for outbound network activity with no way to tell what it actually was.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;Digging into the Powertools Tracer source code revealed the culprit:&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;// Tracer.js, inside the constructor&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isTracingEnabled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;captureHTTPsRequests&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureHTTPsGlobal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instrumentFetch&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;&lt;code&gt;captureHTTPsRequests&lt;/code&gt; &lt;strong&gt;defaults to &lt;code&gt;true&lt;/code&gt;&lt;/strong&gt;. This means Powertools Tracer was &lt;em&gt;silently&lt;/em&gt; patching Node's core &lt;code&gt;http&lt;/code&gt;/&lt;code&gt;https&lt;/code&gt; module on every cold start, the exact same kind of monkey-patching that's known to misbehave on Node.js 24's updated internals. It wasn't crashing outright, but it was producing broken, unlabeled subsegments instead of properly-tagged ones (or in some cases, nothing at all).&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Two changes, both verified against the actual library source before applying:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Turn off the broken auto-instrumentation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracer&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;Tracer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;XYZ_Backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;captureHTTPsRequests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;2. Manually wrap external calls, and mark them correctly for the trace map:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;traceExternalCall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operation&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;segment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSegment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;segment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;operation&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;subsegment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;segment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNewSubsegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- tells X-Ray to render this as its own node&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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;The &lt;code&gt;namespace = "remote"&lt;/code&gt; line matters more than it looks; it's literally the same flag the AWS X-Ray SDK's own HTTP patcher sets internally when it recognizes an external call. Without it, a subsegment just sits in the timeline list; with it, X-Ray draws it as a proper node on the trace map.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making It Automatic, Not Manual-Per-Function
&lt;/h3&gt;

&lt;p&gt;Rather than wrapping every Mongo/Stripe/PayPal call across 50+ files by hand, we centralized the fix into the few shared places all those calls already flow through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MongoDB&lt;/strong&gt;: wrapped once, inside the shared &lt;code&gt;connectToDb()&lt;/code&gt; helper. Every function that connects to Mongo gets a &lt;code&gt;MongoDB-Connect&lt;/code&gt; node automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe&lt;/strong&gt;: the Stripe SDK exposes native &lt;code&gt;request&lt;/code&gt;/&lt;code&gt;response&lt;/code&gt; events. We hooked into those once, inside our shared &lt;code&gt;initializeStripe()&lt;/code&gt; factory:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&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;event&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subsegment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSegment&lt;/span&gt;&lt;span class="p"&gt;()?.&lt;/span&gt;&lt;span class="nf"&gt;addNewSubsegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api.stripe.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;openSubsegments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request_start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&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;event&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subsegment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;openSubsegments&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="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request_start_time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addErrorFlag&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;PayPal / Zoho / Coda / any HTTP call via axios&lt;/strong&gt; a single global interceptor on the shared &lt;code&gt;axios&lt;/code&gt; instance, since every one of these services happens to call out via axios:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;config&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;host&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;hostname&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;subsegment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSegment&lt;/span&gt;&lt;span class="p"&gt;()?.&lt;/span&gt;&lt;span class="nf"&gt;addNewSubsegment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xraySubsegment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subsegment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xraySubsegment&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&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;span class="nx"&gt;error&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;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;xraySubsegment&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Result: &lt;strong&gt;zero code changes needed per new function&lt;/strong&gt;, as long as it reuses these shared utilities. "Unknown host" nodes were replaced with correctly-labeled &lt;code&gt;MongoDB-Connect&lt;/code&gt;, &lt;code&gt;api.stripe.com&lt;/code&gt;, &lt;code&gt;api-m.paypal.com&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem #2: Seeing SQS Producer → Consumer Flows
&lt;/h2&gt;

&lt;p&gt;Our architecture is heavily queue-based: a webhook function does its work, then drops a message on an SQS queue; a separate Lambda, triggered by that queue, picks it up and continues (e.g. writing to MongoDB). We wanted to see that whole chain as one connected story in X-Ray.&lt;/p&gt;

&lt;h3&gt;
  
  
  First (Wrong) Conclusion
&lt;/h3&gt;

&lt;p&gt;Our first attempt used the classic pattern of reading the SQS message's &lt;code&gt;AWSTraceHeader&lt;/code&gt; attribute and manually overwriting the consumer's segment &lt;code&gt;trace_id&lt;/code&gt;/&lt;code&gt;parent_id&lt;/code&gt; to match the producer's. We tested it directly, injected a known fake trace ID into a synthetic SQS event, invoked the consumer, and checked what trace ID it reported.&lt;/p&gt;

&lt;p&gt;It didn't work. The consumer always reported its own, fresh trace ID, regardless of what we injected. We confirmed this at the API level too, using &lt;code&gt;aws xray get-trace-graph&lt;/code&gt; on the producer's trace ID; the consumer never appeared in the graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; on Lambda, the top-level trace ID is assigned by the AWS Lambda platform &lt;em&gt;before&lt;/em&gt; your code runs. Application code can't override it after the fact, that door is locked from the platform side. This is different from services like ECS/EC2, where the X-Ray SDK itself creates the root segment and &lt;em&gt;can&lt;/em&gt; be told what trace ID to use.&lt;/p&gt;

&lt;p&gt;We initially documented this as "SQS producer→consumer tracing isn't possible on Node 24 without ADOT" and moved on.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Correction
&lt;/h3&gt;

&lt;p&gt;I later discovered we'd tested the wrong thing. AWS has a &lt;strong&gt;separate mechanism&lt;/strong&gt; "linked traces" that connects two distinct trace IDs together &lt;em&gt;for console viewing&lt;/em&gt;, without merging them into one trace ID. Opening the consumer's trace in the X-Ray console showed a banner: &lt;strong&gt;"This trace is part of a linked set of traces"&lt;/strong&gt;, with the producer trace displayed alongside it, connected.&lt;/p&gt;

&lt;p&gt;This worked because the &lt;code&gt;AWSTraceHeader&lt;/code&gt; was already being correctly propagated onto the SQS message (this part worked from the start) X-Ray's console uses that header to link the two traces together for display, even though they remain separate IDs under the hood.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making the Queue Itself Visible
&lt;/h3&gt;

&lt;p&gt;One more piece was missing: our SQS client wasn't wrapped with any tracing at all, so the actual "send to queue" step was invisible, and the queue never appeared as its own node on the trace map. The fix was a single line, in the one shared place all our queue sends flow through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// common/services/messageQueue.service.ts&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messageQueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureAWSv3Client&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;SQSClient&lt;/span&gt;&lt;span class="p"&gt;({}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;captureAWSv3Client&lt;/code&gt; hooks into the AWS SDK v3's own middleware stack (not Node's core modules), so it's unaffected by the Node 24 monkey-patching issues entirely. After this change, the Trace Map showed the SQS queue as an explicit node &lt;code&gt;https://sqs.../XYZSaveUsersQueue.fifo&lt;/code&gt; sitting visually between the producer and consumer functions, with the queue's real URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  End Result
&lt;/h3&gt;

&lt;p&gt;For a real signup flow (&lt;code&gt;postConfirmationFunction&lt;/code&gt; → SQS → &lt;code&gt;saveUsersFunction&lt;/code&gt;), the Trace Map now shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → postConfirmation (Lambda) → SQS Queue → saveUsers (Lambda) → MongoDB-Connect
                                                                     → MongoDB-FindUser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the linked-traces banner connecting the two Lambda traces, and the MongoDB node showing "Ok 100%" with zero faults a fully connected, correctly labeled, verified-working picture of the whole flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verify library defaults, don't assume them.&lt;/strong&gt; The "Unknown host" bug existed because a &lt;code&gt;true&lt;/code&gt; default was silently active the whole time. Reading the actual source code (&lt;code&gt;Tracer.js&lt;/code&gt;) settled it in minutes, versus hours of guessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test claims empirically, especially "automatic" ones.&lt;/strong&gt; AWS's own documentation implied SQS linking "just works" for Lambda consumers. It doesn't not the way we first tested it. The real feature (linked traces) exists, but it's a different mechanism than the docs' wording suggested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralize instrumentation, don't scatter it.&lt;/strong&gt; Wrapping ~5 shared utility files (Mongo connect, Stripe factory, axios instance, SQS service) gave us tracing coverage across 50+ functions, with zero risk of new functions being "forgotten." The only manual step left is wrapping each new handler's export in &lt;code&gt;withMetrics&lt;/code&gt; a single line, documented in our dev guide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js version currency has real, unglamorous costs.&lt;/strong&gt; Being on the newest Node runtime meant losing access to AWS's newest tracing tooling (ADOT) for the time being. That's a real trade-off, not a bug to route around.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Production Considerations Going Forward
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sampling:&lt;/strong&gt; X-Ray doesn't trace every request by default (1/sec + 5% of the rest). What we tested manually (1 request at a time) always gets sampled; production traffic won't be 100% visible without tuning sampling rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alarms over eyeballs:&lt;/strong&gt; the Trace Map is a "glance and check" tool, not something to watch live. Real usage means CloudWatch Alarms on fault rate/latency, with traces used for investigation &lt;em&gt;after&lt;/em&gt; an alarm fires.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annotations for searchability:&lt;/strong&gt; to find one specific customer's failed transaction later, we plan to add searchable annotations (e.g. order ID) to segments something to build next.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>data</category>
      <category>systemdesign</category>
      <category>node</category>
    </item>
    <item>
      <title>Amazon Q CLI: Rock Paper Scissor with Python 🕹️</title>
      <dc:creator>M. Abdullah Bin Aftab</dc:creator>
      <pubDate>Wed, 04 Jun 2025 04:35:40 +0000</pubDate>
      <link>https://dev.to/heighter/amazon-q-cli-rock-paper-scissor-with-python-2o9f</link>
      <guid>https://dev.to/heighter/amazon-q-cli-rock-paper-scissor-with-python-2o9f</guid>
      <description>&lt;p&gt;In this blog post, I'll walk you through my journey of creating a fun &lt;strong&gt;Rock Paper Scissors&lt;/strong&gt; game using Python and Pygame, with the assistance of &lt;strong&gt;Amazon Q CLI&lt;/strong&gt;. I'll cover everything from setting up the development environment to implementing game mechanics and generating custom assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Installing Amazon Q CLI on macOS
&lt;/h2&gt;

&lt;p&gt;Amazon Q CLI is a powerful tool that helped me throughout the development process. Here's how I installed it on my macOS:&lt;/p&gt;

&lt;p&gt;First install the AWS CLI using Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install awscli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I configured my AWS credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I installed the Amazon Q CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install amazon-q-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, I verified it was working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I started using Amazon Q by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the chat, I asked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you help me structure a Rock Paper Scissors game using Pygame?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amazon Q CLI became my coding companion, helping me generate code snippets, debug issues, and even create project documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎮 Designing the Game Structure
&lt;/h2&gt;

&lt;p&gt;Based on Amazon Q's suggestions, I designed the game with three main states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Menu State:&lt;/strong&gt; The main menu where players can start the game.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Playing State:&lt;/strong&gt; Where players select their move (Rock, Paper, or Scissors).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result State:&lt;/strong&gt; Displaying the outcome and allowing players to play again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I created the main game file structure with Amazon Q's help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I asked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you help me create a main.py file for my Rock Paper Scissors game with state management?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎯 Implementing Game Mechanics
&lt;/h2&gt;

&lt;p&gt;For the core game mechanics, I needed to implement:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Player choice selection&lt;/li&gt;
&lt;li&gt;Computer random choice generation&lt;/li&gt;
&lt;li&gt;Winner determination logic&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🎁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building this Rock Paper Scissors game was a fun and educational experience. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon Q CLI significantly accelerated my development process by:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Providing code snippets and structure&lt;/li&gt;
&lt;li&gt;Helping debug issues quickly&lt;/li&gt;
&lt;li&gt;Generating documentation&lt;/li&gt;
&lt;li&gt;Offering best practices and optimization tips&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The final game includes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An intuitive user interface&lt;/li&gt;
&lt;li&gt;Smooth animations and transitions&lt;/li&gt;
&lt;li&gt;Visual feedback with particle effects&lt;/li&gt;
&lt;li&gt;Custom-generated game assets&lt;/li&gt;
&lt;li&gt;Multiple game states for a complete experience&lt;/li&gt;
&lt;li&gt;If you're developing games or any software project, I highly recommend giving Amazon Q CLI a try. It's like having an expert developer by your side, ready to help whenever you need it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🕹️ To run the game yourself:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git clone https://https://github.com/heighterses/rock-paper-scissor-Q-CLI&lt;/code&gt;&lt;br&gt;
&lt;code&gt;cd rock-paper-scissor-Q-CLI&lt;/code&gt;&lt;br&gt;
&lt;code&gt;pip install pygame&lt;/code&gt;&lt;br&gt;
&lt;code&gt;python main.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoy playing Rock Paper Scissors! 🎮&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>amazonqcli</category>
      <category>amazondeveloper</category>
    </item>
    <item>
      <title>Case Study: Creating an ETL Data Pipeline using AWS Services - Real-World Problem</title>
      <dc:creator>M. Abdullah Bin Aftab</dc:creator>
      <pubDate>Fri, 06 Dec 2024 18:04:47 +0000</pubDate>
      <link>https://dev.to/heighter/case-study-creating-an-etl-data-pipeline-using-aws-services-real-world-problem-1e40</link>
      <guid>https://dev.to/heighter/case-study-creating-an-etl-data-pipeline-using-aws-services-real-world-problem-1e40</guid>
      <description>&lt;h2&gt;
  
  
  Architecture
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2F4qmojb210e1coimc4d29.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.amazonaws.com%2Fuploads%2Farticles%2F4qmojb210e1coimc4d29.png" alt=" " width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This ETL pipeline leverages several AWS services to fetch, process, and store YouTube videos with translated subtitles. The core components include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Lambda for processing video and audio&lt;/li&gt;
&lt;li&gt;Step Functions for Orchestrating Workflows&lt;/li&gt;
&lt;li&gt;S3 Buckets for storing raw and processed data&lt;/li&gt;
&lt;li&gt;AWS Transcribe for converting audio to text&lt;/li&gt;
&lt;li&gt;AWS Translate for translating the text into desired languages&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pipeline Steps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fetching Video from YouTube&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Video is fetched from YouTube and sent to an initial Lambda Function.&lt;/li&gt;
&lt;li&gt;This function splits the video into separate audio and video files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step Functions Orchestration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Step Functions orchestrate all the following processes.&lt;/li&gt;
&lt;li&gt;The workflow controls each step, passing data between services and managing the pipeline flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Storing Raw Video and Audio&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Audio and video files are stored separately here.&lt;/li&gt;
&lt;li&gt;The bucket sends an email notification to confirm the files were successfully stored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Merging Video and Audio Files&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This Lambda function combines the audio and video files into a single file.&lt;/li&gt;
&lt;li&gt;Error Handling: If merging fails, the pipeline stores the failed files in an Error Bucket.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Transcribing Audio to Text&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The merged video’s audio is sent to AWS Transcribe to convert audio into text.&lt;/li&gt;
&lt;li&gt;The resulting text is passed to the next Lambda function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Proofreading Transcribed Text&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This Lambda function checks the transcription for accuracy and readability.&lt;/li&gt;
&lt;li&gt;If the text is poor quality, it can be flagged for manual review or re-transcription.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Translating Text into Target Language&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The proofread text is sent to AWS Translate to convert it into a chosen language (e.g., Arabic, Italian, or Spanish).&lt;/li&gt;
&lt;li&gt;The translated text is then passed to the next Lambda function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generating Subtitles and Merging Paragraphs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This function formats the translated text as subtitles and merges paragraphs if needed.&lt;/li&gt;
&lt;li&gt;The final file is prepared for storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Storing Processed Video with Subtitles&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The fully processed video with subtitles in the desired language is stored here.&lt;/li&gt;
&lt;li&gt;This is the final output location where the processed video is accessible.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Error Bucket for Failed Merges:&lt;/strong&gt; If audio and video files fail to merge, the Lambda Merge Function sends them to a designated Error Bucket.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transcription and Proofreading Quality Check:&lt;/strong&gt; Poor transcription quality detected by the Proofread Function can trigger a flag for manual review or re-transcription.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Notifications
&lt;/h2&gt;

&lt;p&gt;**Email Notifications **for File Arrival in S3:After the raw video and audio files are stored in the S3 Raw Video and Audio Bucket, an email notification is sent to confirm successful storage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits of This Pipeline
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Automation:&lt;/strong&gt; Streamlines the entire video processing workflow without manual intervention.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; AWS services like Lambda and Step Functions allow the pipeline to handle many videos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language Support:&lt;/strong&gt; AWS Translate enables easy translation to multiple languages, broadening the video’s reach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Management:&lt;/strong&gt; Dedicated error-handling buckets and flags ensure issues are logged and handled efficiently.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>aws</category>
      <category>dataengineering</category>
      <category>data</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>How to Import Pandas(library) in AWS Lambda Functions - AWS Lambda Layers</title>
      <dc:creator>M. Abdullah Bin Aftab</dc:creator>
      <pubDate>Wed, 16 Oct 2024 19:13:43 +0000</pubDate>
      <link>https://dev.to/heighter/how-to-import-pandaslibrary-in-aws-lambda-functions-aws-lambda-layers-1oen</link>
      <guid>https://dev.to/heighter/how-to-import-pandaslibrary-in-aws-lambda-functions-aws-lambda-layers-1oen</guid>
      <description>&lt;p&gt;Imagine you need to run a Python script on the AWS Lambda function and you get this error 🔻&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "errorMessage": "Unable to import module 'lambda_function': No module named 'pandas',
  "errorType": "Runtime.ImportModuleError"
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Don't worry this is a common error and I am not going to make this long&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How do you import Pandas in AWS Lambda Functions?
&lt;/h2&gt;

&lt;p&gt;There are several ways but I am going to give you the easiest way to import pandas in AWS Lambda Function is to add Lambda Layer 🥪&lt;/p&gt;

&lt;h4&gt;
  
  
  What is AWS Lambda Layer?
&lt;/h4&gt;

&lt;p&gt;It is a 🧀 cheese layer in Lambda Function containing additional code like libraries, dependencies, etc.&lt;/p&gt;

&lt;h5&gt;
  
  
  In Simple Words
&lt;/h5&gt;

&lt;p&gt;AWS Lambda Layers are like building blocks for your functions. &lt;strong&gt;Imagine&lt;/strong&gt; you need extra tools (like the Pandas library) to complete a project.&lt;/p&gt;

&lt;p&gt;Instead of packing all those tools inside every single project (which wastes space and time), AWS allows you to create layers of tools (libraries, dependencies, or shared code). &lt;/p&gt;

&lt;p&gt;These layers sit outside your main function but are always available when your function needs them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In short, Lambda Layers help you:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Separate the main logic from the extra libraries to save space in your code. You can reuse libraries and code across multiple Lambda functions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Easily update or manage your dependencies without changing your core function code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of layers as an extra storage box attached to your Lambda function, holding everything your function needs to work smoothly. You can stack multiple layers on your function without cluttering your main code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to add Lambda Function Layer and Import Pandas
&lt;/h2&gt;

&lt;p&gt;It takes only 3 steps to run Pandas in your Lambda Function successfully&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Open Lambda Function through your AWS Management Console
&lt;/h3&gt;

&lt;p&gt;As you can see we have an option &lt;strong&gt;Layers&lt;/strong&gt; under the name of our Lambda Function, in my case, it's &lt;em&gt;"import-pandas-function"&lt;/em&gt; and the Layers count is &lt;strong&gt;0&lt;/strong&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fabn0rsvdm5tsuld3c78c.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.amazonaws.com%2Fuploads%2Farticles%2Fabn0rsvdm5tsuld3c78c.png" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2- Add Script in your AWS Lambda Function
&lt;/h3&gt;

&lt;p&gt;This step is further divided into two steps because we need to add a Python script that contains some Pandas code and write a test event in JSON to verify whether the code is running correctly.&lt;/p&gt;

&lt;h4&gt;
  
  
  2.1 - Add Python script - you can copy this code 🡻
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import pandas as pd

def lambda_handler(event, context):
    data = event.get('data', [])

    df = pd.DataFrame(data)

    if not df.empty:
        mean_value = df['column_name'].mean()

        result = {
            "mean_value": mean_value,
            "data_shape": df.shape,
            "summary": df.describe().to_dict()
        }
    else:
        result = {
            "message": "Empty DataFrame"
        }

    # Return the response
    return {
        'statusCode': 200,
        'body': json.dumps(result)
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.2 - Add Test script in Json in the test tab - you can copy this code 🡻
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": [
    {"column_name": 10, "other_column": "A"},
    {"column_name": 20, "other_column": "B"},
    {"column_name": 30, "other_column": "C"},
    {"column_name": 40, "other_column": "D"}
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Press the test button you probably got the 🔴error:-&lt;br&gt;
&lt;code&gt;"errorMessage": "Unable to import module 'lambda_function': No module named 'pandas',&lt;br&gt;
  "errorType": "Runtime.ImportModuleError"&lt;br&gt;
  ...&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3 - Add AWS Lambda Layer to Successfully run the Pandas in your  Code
&lt;/h2&gt;

&lt;p&gt;Scroll down to your Lambda Function, you probably can see the "&lt;strong&gt;Layers&lt;/strong&gt;" separate section at the end of the page&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2F17grr4nr4oiwg2q0dq4v.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.amazonaws.com%2Fuploads%2Farticles%2F17grr4nr4oiwg2q0dq4v.png" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3.1 - Click "Add a Layer"
&lt;/h4&gt;

&lt;p&gt;After Clicking the "Add a Layer" you can see the page which has a couple of sections "Function runtime settings" and "Choose a layer"&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fhnejuqy0vir917to8vi0.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.amazonaws.com%2Fuploads%2Farticles%2Fhnejuqy0vir917to8vi0.png" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3.2 - Click "AWS layers"
&lt;/h4&gt;

&lt;p&gt;You can see three options in the "Choose a layer" section click the "AWS layers".&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Frwp9ns0t7o0p5nx3ta2w.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.amazonaws.com%2Fuploads%2Farticles%2Frwp9ns0t7o0p5nx3ta2w.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3.3 - Choose "AWS layers"
&lt;/h4&gt;

&lt;p&gt;After selecting the AWS layers you can see the dropdown under "AWS layers".&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fkbzeshtplbmnvktjt0ch.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.amazonaws.com%2Fuploads%2Farticles%2Fkbzeshtplbmnvktjt0ch.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3.4 - Choose "AWS layers" and "Version"
&lt;/h4&gt;

&lt;p&gt;In a dropdown of "AWS layers" select -&amp;gt; &lt;strong&gt;AWSSDKPandas-Python312&lt;/strong&gt;&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fg2u5k77yik3mdmsg64ba.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.amazonaws.com%2Fuploads%2Farticles%2Fg2u5k77yik3mdmsg64ba.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
In a dropdown of "Version" select -&amp;gt; &lt;strong&gt;13(select the most one)&lt;/strong&gt;&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fcjyama9hl5yfwnb59c7q.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.amazonaws.com%2Fuploads%2Farticles%2Fcjyama9hl5yfwnb59c7q.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
click the "Add" button&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fw7h2f3afl3pf8t6dq9yl.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.amazonaws.com%2Fuploads%2Farticles%2Fw7h2f3afl3pf8t6dq9yl.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3.5 - Make sure the "Function Overview"
&lt;/h4&gt;

&lt;p&gt;When your page is directed to the function overview you can see the layer is added below the function name "import-pandas-function"&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2F34yb2fx9lk2d9bygh30c.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.amazonaws.com%2Fuploads%2Farticles%2F34yb2fx9lk2d9bygh30c.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4 - Test the Function
&lt;/h2&gt;

&lt;p&gt;You've successfully got the Response &lt;em&gt;"statusCode": 200&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "statusCode": 200,
  "body": "{\"mean_value\": 25.0, \"data_shape\": [4, 2], \"summary\": {\"column_name\": {\"count\": 4.0, \"mean\": 25.0, \"std\": 12.909944487358056, \"min\": 10.0, \"25%\": 17.5, \"50%\": 25.0, \"75%\": 32.5, \"max\": 40.0}}}"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fmyvwqocbt1a9k6wkwuwn.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.amazonaws.com%2Fuploads%2Farticles%2Fmyvwqocbt1a9k6wkwuwn.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Keep Coding 😎&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>python</category>
      <category>cloudcomputing</category>
    </item>
  </channel>
</rss>
