<?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: Ifeanyi O.</title>
    <description>The latest articles on DEV Community by Ifeanyi O. (@ifeanyiro).</description>
    <link>https://dev.to/ifeanyiro</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1228459%2Fd99a6804-bbdc-45d0-bf2a-e118d31c7b19.jpeg</url>
      <title>DEV Community: Ifeanyi O.</title>
      <link>https://dev.to/ifeanyiro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ifeanyiro"/>
    <language>en</language>
    <item>
      <title>I Built My Mom an AI Recipe Helper for Mother's Day</title>
      <dc:creator>Ifeanyi O.</dc:creator>
      <pubDate>Fri, 08 May 2026 07:53:25 +0000</pubDate>
      <link>https://dev.to/aws/i-built-my-mom-an-ai-recipe-helper-for-mothers-day-2hc5</link>
      <guid>https://dev.to/aws/i-built-my-mom-an-ai-recipe-helper-for-mothers-day-2hc5</guid>
      <description>&lt;p&gt;&lt;em&gt;A project about a fridge, Strands agents &amp;amp; trying to keep up with Mom's seasons.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Mom's Problem
&lt;/h2&gt;

&lt;p&gt;My mom has a drawer full of recipes. Yes! Not a folder.... an actual drawer. Torn pages from magazines, things written on the back of envelopes and binders that've been around longer than I have. Whenever she's looking for dinner ideas she pulls something out, sighs and puts it back.&lt;/p&gt;

&lt;p&gt;The recipe is not the issue here, that's always fine. It's that she's missing one ingredient or four!&lt;/p&gt;

&lt;p&gt;And even if she has everything, the recipe might not fit whatever season she's in at the moment because the other thing is, her eating is a moving target.&lt;/p&gt;

&lt;p&gt;One month she's a vegetarian because a friend got her into it, a few months later she's watching her sugar because the doctor mentioned it during a checkup, then it's low sodium or she's "just trying to be a little better with dinners." You just never really know which version is going to be at the stove on a given Tuesday.&lt;br&gt;
But the real question she's always asking, underneath the recipe hunt, is...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What could I make with what I already have, that fits how I'm eating right now, that I won't get bored with?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that sounds like problem for an agent! So for Mother's Day this year, I built her one and called it &lt;strong&gt;AskMom Recipes&lt;/strong&gt;. You can try it out &lt;a href="https://d12rcxds4c00cm.cloudfront.net?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;here&lt;/a&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%2Fm6apyp315q3uawdotk4h.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%2Fm6apyp315q3uawdotk4h.png" alt=" " width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does in 30 seconds
&lt;/h2&gt;

&lt;p&gt;You open a pink website and tell it what's in your kitchen. You can type it, or you can just take a photo of your groceries on the counter and drop it in.&lt;/p&gt;

&lt;p&gt;You also have the option to pick how you're eating this week, for eg. no restriction, vegetarian, low sodium, diabetic-friendly or gluten-free. Then hit the "&lt;strong&gt;Suggest recipes&lt;/strong&gt;" button.&lt;br&gt;
A couple seconds later, you'll get three recipes and each one tells you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What you already have vs. what you'd need to grab&lt;/li&gt;
&lt;li&gt;Simple, unfussy steps (the kind of thing my mom actually cooks)&lt;/li&gt;
&lt;li&gt;Why it's good for you, with real nutrition numbers from the USDA&lt;/li&gt;
&lt;li&gt;One sentence about where the dish possibly comes from&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't love the recipes, you can tap "&lt;strong&gt;make it healthier&lt;/strong&gt;" or "&lt;strong&gt;something quicker&lt;/strong&gt;" or "&lt;strong&gt;fewer ingredients&lt;/strong&gt;" and it adjusts on the fly.&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%2Fxxod5fswq7pcfvwvt13m.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%2Fxxod5fswq7pcfvwvt13m.png" alt=" " width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! The rest of this blog is how I built it and the design decisions that made the difference between "&lt;strong&gt;okay, cool demo that kinda works&lt;/strong&gt;" and "&lt;strong&gt;something my mom would actually use.&lt;/strong&gt;"&lt;/p&gt;
&lt;h2&gt;
  
  
  Why an agent and not a prompt
&lt;/h2&gt;

&lt;p&gt;An easy version of this would just be to throw the ingredients into a single prompt, ask for three recipes, done. I tried it, it's fine but there's problems that show up the moment you try to use it for real.&lt;br&gt;
First, the model will happily make up nutrition numbers. Ask it how much protein is in chicken and it'll give you a number, confidently and you'll have no idea if it's right.&lt;/p&gt;

&lt;p&gt;Second, it'll cheerfully tell you that tomatoes come from Italy or that pasta is a Chinese invention. Third, if you want to say "&lt;strong&gt;actually, make that healthier&lt;/strong&gt;" the prompt has to start over from scratch because there's no memory.&lt;/p&gt;

&lt;p&gt;An agent solves two of those three. As for the made up facts we needed something else which we'll get.&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://strandsagents.com" rel="noopener noreferrer"&gt;Strands Agents&lt;/a&gt;, which is a refreshingly simple Python SDK for building agents on Amazon Bedrock. You define your tools as functions, write a system prompt and Strands handles the loop of "&lt;strong&gt;model decides what tool to call, tool runs, result goes back to model, repeat.&lt;/strong&gt;"&lt;/p&gt;

&lt;p&gt;It's the first agent framework I've used that didn't make me want to throw my laptop.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;model_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_id&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BEDROCK_MODEL_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic.claude-3-haiku-20240307-v1:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AWS_REGION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BedrockModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;extract_ingredients_from_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;extract_ingredients_from_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;suggest_recipes&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;With Strands, setting up the agent is almost anticlimactic. There's a model, a prompt and a list of tools. That's the whole thing.&lt;/p&gt;

&lt;p&gt;I wanted to flag this, because it took me a few iterations to get right, the tools I gave the agent are not "&lt;strong&gt;one tool for everything.&lt;/strong&gt;" They're small, single-purpose and named like verbs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tools and why there aren't very many
&lt;/h2&gt;

&lt;p&gt;Everyone always goes tool crazy, when they first build an agent. Each tool feels free so why not just add them all, right? Wrong!&lt;/p&gt;

&lt;p&gt;The problem is every tool call is another round trip through the model. The model says "&lt;strong&gt;I'd like to call X,&lt;/strong&gt;" you run X, hand the result back, it thinks for a second and says "&lt;strong&gt;now I'd like to call Y.&lt;/strong&gt;" Each hop is a few seconds but when you add six tool calls, then your recipe helper takes forty seconds and your API times out.&lt;/p&gt;

&lt;p&gt;So I decided to split the work in two:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Things the agent handles&lt;/strong&gt; (because they genuinely need a model's judgment):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading a photo and identifying what's in it&lt;/li&gt;
&lt;li&gt;Normalizing messy text like "some chicken, rice, maybe garlic" into a clean list&lt;/li&gt;
&lt;li&gt;Generating three healthy recipes that fit the user's preferences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Things Python handles&lt;/strong&gt; (because they just need a lookup):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looking up real nutrition numbers&lt;/li&gt;
&lt;li&gt;Formatting a recipe card for the frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since Python can fetch faster than the model can ask, why would I let a language model guess when there's a real source? USDA has an API with the actual nutrition numbers.&lt;/p&gt;

&lt;p&gt;This one design decision cut request latency from ~34 seconds to ~17 seconds. You get the same quality in half the time with way less money spent on Bedrock tokens and it made the agent more reliable with fewer retries and self corrections that eat tokens for no reason.&lt;/p&gt;

&lt;p&gt;The lesson is to use the LLM for the things that need reasoning and use code for the things that need answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preference handling
&lt;/h2&gt;

&lt;p&gt;Alright, back to my mom for a second. The seasons thing, vegetarian one month and low sodium the next taught me more about preference handling that I didn't expect.&lt;/p&gt;

&lt;p&gt;The naive approach is a freeform text field that ask you to type your dietary preferences. The problem is the model has to figure out what "&lt;strong&gt;watching my sugar a bit&lt;/strong&gt;" means versus "&lt;strong&gt;diabetic-friendly&lt;/strong&gt;" versus "low-carb." Sometimes it guesses wrong and sometimes the recipes it produces have way too much added.&lt;/p&gt;

&lt;p&gt;So I made it a dropdown. Five options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No restriction&lt;/li&gt;
&lt;li&gt;Vegetarian&lt;/li&gt;
&lt;li&gt;Low sodium&lt;/li&gt;
&lt;li&gt;Diabetic-friendly&lt;/li&gt;
&lt;li&gt;Gluten-free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each one maps to a crisp, one sentence guidance block that gets injected into the recipe prompt:&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="n"&gt;_PREFERENCE_GUIDANCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;none&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No dietary restrictions. Focus on healthy, balanced meals.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vegetarian&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Strictly vegetarian: no meat, poultry, or fish.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low_sodium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Low sodium: minimize salt and high-sodium ingredients like soy sauce or canned broths.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;diabetic_friendly&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Diabetic-friendly: low glycemic index, limit added sugars and refined carbs.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gluten_free&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Strictly gluten-free: no wheat, barley, rye, or standard soy sauce.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's five lines of Python. &lt;/p&gt;

&lt;p&gt;A dropdown sounds less impressive than "&lt;strong&gt;the AI understands your preferences,&lt;/strong&gt;" but the dropdown is more reliable and trust me, reliable is what my mom needs.&lt;/p&gt;

&lt;p&gt;When it comes to agent patterns, the more you can constrain the inputs, the better the outputs. Freeform is cool in demos but more structure is better in real life.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "send a photo of your groceries" part
&lt;/h2&gt;

&lt;p&gt;I wanted to keep the typed-ingredients path simple, but the photo path is where it gets fun. You take a picture of whatever's on your counter and the agent reads the photo, identifies the food and treats it the same as if you'd typed it in.&lt;/p&gt;

&lt;p&gt;Under the hood this is one of Strands' best party tricks. Claude 3 Haiku on Bedrock handles vision natively, so the whole thing is one tool call:&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="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_ingredients_from_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s3_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Look at a photo of groceries and return the ingredients visible in it.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPLOADS_BUCKET_NAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AWS_REGION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 1. Fetch image bytes from S3
&lt;/span&gt;    &lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s3_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;image_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;media_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obj&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ContentType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image/jpeg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Ask Bedrock Claude Haiku what's in the photo
&lt;/span&gt;    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;List only the food ingredients you can clearly see in this photo. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return a JSON array of short lowercase names, nothing else. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Example: [&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tomato&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;onion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chicken breast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;]. &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If you can&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t identify any food, return [].&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bedrock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock-runtime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bedrock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BEDROCK_MODEL_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic_version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock-2023-05-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;base64&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;media_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;media_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;standard_b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_bytes&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&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;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Pull the JSON array back out (defensively)
&lt;/span&gt;    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\[.*?\]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DOTALL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prompt is boring on purpose. All is says is "&lt;strong&gt;List only the food ingredients you can clearly see in this photo. Return a JSON array of short lowercase names, nothing else.&lt;/strong&gt;" I did not give it a personality or tell it to "&lt;strong&gt;please think carefully&lt;/strong&gt;". I also didn't give it examples of how the model should "&lt;strong&gt;reason.&lt;/strong&gt;" I just told it what I want and what format I want it in.&lt;/p&gt;

&lt;p&gt;The model is very good at ambitious prompts and very good at literal ones. Ambitious prompts return ambitious, chatty and often wrong answers but literal prompts more closely return what you asked for. For this tool, where the output feeds directly into the next step, literal wins every time.&lt;/p&gt;

&lt;p&gt;Also, note that the photo gets uploaded straight from the browser to S3 via a pre-signed URL, so my Lambda never has to deal with multipart file uploads. The agent just gets an S3 key and fetches it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Here's the whole thing, in the order a request flows:&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%2Fsz0yeovkw1qrk97nvtbl.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%2Fsz0yeovkw1qrk97nvtbl.png" alt=" " width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser loads static pink site from S3, served through CloudFront.&lt;/li&gt;
&lt;li&gt;User submits text and/or photo. If photo, goes straight to S3 as pre-signed URL.&lt;/li&gt;
&lt;li&gt;Browser calls &lt;code&gt;POST /ingredients&lt;/code&gt; on API Gateway, which hits a Lambda.&lt;/li&gt;
&lt;li&gt;Lambda builds a Strands agent with three tools, runs the agent loop.&lt;/li&gt;
&lt;li&gt;Agent extracts ingredients (text + vision), then calls &lt;code&gt;suggest_recipes&lt;/code&gt; once.&lt;/li&gt;
&lt;li&gt;Lambda enriches each recipe in Python, origin lookup, USDA lookup and format.&lt;/li&gt;
&lt;li&gt;Session is saved to DynamoDB with a 24-hour TTL for the "refine" follow up.&lt;/li&gt;
&lt;li&gt;Recipes come back to the browser.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing is deployed with AWS CDK in Python, one stack, one &lt;code&gt;make deploy&lt;/code&gt;. No Docker needed, no hand-wiring and definitely no clicking around in the console.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs me to keep it running
&lt;/h2&gt;

&lt;p&gt;For my mom's personal deployment, answering a few requests a week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bedrock&lt;/strong&gt;: Tenth of a penny per recipe request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt;: Free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DynamoDB&lt;/strong&gt;: Free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 + CloudFront&lt;/strong&gt;: Couple cents a month for the static site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;USDA API&lt;/strong&gt;: Free.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I pay less for AskMom per month than for a single coffee. If I published it and a hundred people used it regularly, I'd still be under a few dollars a month!&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;If you want to build one for your mom (or your dad, or anyone whose fridge is a mystery), the whole thing is open source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/rextheking/askmom-recipes-sample-for-aws-strands" rel="noopener noreferrer"&gt;github.com/rextheking/askmom-recipes-sample-for-aws-strands&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The README walks through the deploy in six steps. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with Bedrock access enabled for Claude 3 Haiku in &lt;code&gt;us-east-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Python 3.12, Node 20/22/24, AWS CDK CLI and the AWS CLI&lt;/li&gt;
&lt;li&gt;A free USDA FoodData Central API key (takes 30 seconds to get)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it's:&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;cd &lt;/span&gt;infra
make &lt;span class="nb"&gt;install
&lt;/span&gt;make bootstrap     &lt;span class="c"&gt;# one time per AWS account&lt;/span&gt;
make deploy        &lt;span class="c"&gt;# ~5-7 minutes, most of it CloudFront&lt;/span&gt;
&lt;span class="c"&gt;# paste the ApiUrl into web/config.js&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ../web
make deploy
&lt;span class="c"&gt;# open the CloudFront URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, the first deploy takes a few minutes because CloudFront is slow to propagate. If you're just kicking the tires, there's a &lt;code&gt;-c with_cloudfront=false&lt;/code&gt; flag that skips CloudFront and gets you a working API in about 90 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hug
&lt;/h2&gt;

&lt;p&gt;If you build something for your mom this year, I'd love to see it. Tag me or share the repo of whatever weird thing you shipped.&lt;/p&gt;

&lt;p&gt;Happy Mother's Day 💖&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%2Fmbox7zkb7p2i5ekulh7p.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%2Fmbox7zkb7p2i5ekulh7p.png" alt=" " width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://strandsagents.com" rel="noopener noreferrer"&gt;Strands Agents&lt;/a&gt; for making agent code actually pleasant to write&lt;/li&gt;
&lt;li&gt;Amazon Bedrock + Claude 3 Haiku for the model&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fdc.nal.usda.gov/api-guide.html" rel="noopener noreferrer"&gt;USDA FoodData Central&lt;/a&gt; for free, honest nutrition data&lt;/li&gt;
&lt;li&gt;My mom, for the original problem&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>agents</category>
      <category>mothersday</category>
    </item>
    <item>
      <title>How to Survive Your First 90 Days as a Developer</title>
      <dc:creator>Ifeanyi O.</dc:creator>
      <pubDate>Mon, 04 May 2026 05:00:00 +0000</pubDate>
      <link>https://dev.to/aws/how-to-survive-your-first-90-days-as-a-developer-1ean</link>
      <guid>https://dev.to/aws/how-to-survive-your-first-90-days-as-a-developer-1ean</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;The Psychological Transition&lt;/li&gt;
&lt;li&gt;Clarity Through Your Manager&lt;/li&gt;
&lt;li&gt;Learning the System&lt;/li&gt;
&lt;li&gt;Choose Depth Over Breath&lt;/li&gt;
&lt;li&gt;The Codebase&lt;/li&gt;
&lt;li&gt;Relationships&lt;/li&gt;
&lt;li&gt;A Strong First 90 Days&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="Intro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;If you've spent enough time on LinkedIn, YouTube, or X (Twitter) over the past 5 years, it's clear how the tech industry has been positioned to new entrants. You're told that with the right roadmap, bootcamp, course, or resources and enough consistency, you can transition into a high-paying role in a relatively short amount of time. You see titles that promise six-figure salaries without a degree, structured paths to be a full-stack developer or cloud engineer, with step-by-step breakdowns of how others have made the transition successfully. For many, this content is as a powerful entry point into an industry they may have never considered and there's real value in that.&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%2Fzjtrevjbg9pey9l2fzit.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%2Fzjtrevjbg9pey9l2fzit.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, there's an issue I have with this messaging, as it often presents an incomplete picture of what the journey actually entails. While there's heavy emphasis on how to learn, build and position yourself to land a role, there's significantly less conversation around what happens once you actually get there. The transition into your first engineering role is not simply a continuation of the learning process you experienced while preparing, it's a complete shift into an entirely different environment, one where expectations, responsibilities and pressures operate at a different level.&lt;/p&gt;

&lt;p&gt;When you step into your first role, you're not operating in isolation anymore or within the controlled structure of courses and tutorials, you're part of a team, contributing to systems already in production, with real users, dependencies and consequences tied to the work being done. You're expected to learn quickly, but also to apply that learning in a way that aligns with how the team and organization function.&lt;/p&gt;

&lt;p&gt;This is where many new developers encounter difficulty, because they weren't prepared for what the role actually demands beyond the hiring process. The skills required to pass interviews and complete projects in a learning environment don't always translate directly into the skills required to navigate ambiguity, collaborate within a team and operate effectively within an existing system. As a result, the first few months can and will feel disorienting and in most cases, overwhelming.&lt;/p&gt;

&lt;p&gt;You have to acknowledge that there's a reason these roles are compensated at a high level. When an organization hires an engineer, particularly into a role that carries a six-figure salary, it's making an investment that goes beyond technical knowledge alone. That investment reflects an expectation that the individual will be able to learn rapidly, adapt to complex systems, communicate effectively with others and contribute to outcomes that have a tangible impact on the business. These expectations are't always explicitly stated, but they are very real and immediately become apparent once you begin operating within the role.&lt;/p&gt;

&lt;p&gt;Without a clear understanding of these dynamics, it's not uncommon for new engineers to experience imposter syndrome, uncertainty around expectations and difficulty finding their footing in the early stages of their career. In some cases, this leads to disengagement or burnout and in others, it results in individuals leaving their roles within the first few months, due to a lack of preparation.&lt;/p&gt;

&lt;p&gt;This blog is intended to address that gap. We'll focuses on what it actually takes to navigate your first 90 days as a developer. The period that plays a critical role in shaping how successfully you transition from a new hire into a contributing member of your team.&lt;/p&gt;

&lt;p&gt;&lt;a id="Transition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Psychological Transition
&lt;/h2&gt;

&lt;p&gt;When I stepped into my first role as a cloud developer, I thought I went in with a very clear expectation of what the challenge would look like. I assumed it would be technical in nature and I thought my days would be spent learning new AWS services, writing code, debugging issues and gradually building up my understanding of how everything fit together. In my mind, the difficulty would come from solving problems I'd never seen before and I was mentally prepared for that. What I was not prepared for was how quickly the pressure would shift from external challenges to internal ones.&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%2Fg2b1jxbwezc59wigk2qh.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%2Fg2b1jxbwezc59wigk2qh.png" alt=" " width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within the first few weeks, I started to realize the real difficulty was the environment I was now operating in. I remember sitting in my first few stand ups and team meetings, listening to conversations that moved at a pace I wasn’t used to. People were referencing systems, pipelines, internal tools and architectural decisions as if they were common knowledge. There was an assumed level of context that I simply didn't have yet. I'd hear terms I recognized individually, but not in the way they were being applied in that specific system and I found myself trying to mentally connect everything in real time while the conversation kept moving forward.&lt;/p&gt;

&lt;p&gt;At the same time, I was trying to manage how I was being perceived. I didn’t want to constantly interrupt to ask questions that felt basic because I didn’t want to slow the conversation down so I'd sit there, processing as much as I could, taking notes and telling myself I'd go figure it out later. That combination, high exposure to new information and hesitation to reveal gaps in understanding created a very specific kind of pressure.&lt;/p&gt;

&lt;p&gt;It’s hard to fully describe that feeling unless you’ve experienced it, but it’s the moment where you begin to question your own presence in the room. You start to wonder whether everyone else is operating at a level you somehow missed and whether you're the only one trying to catch up. That internal dialogue becomes louder over time, especially when each day introduces something new that you don’t yet understand.&lt;/p&gt;

&lt;p&gt;For me, it reached a point where I genuinely considered walking away from the role. It gotten to the point where I felt like I was falling behind in real time and every day felt like a new layer of complexity was being added, but instead of interpreting that as part of the learning process, I saw it as evidence that I wasn’t progressing fast enough. I was measuring myself against an expectation that didn’t align with reality.&lt;/p&gt;

&lt;p&gt;Looking back, that was a fundamental misunderstanding of what the first 90 days are supposed to feel like. The discomfort, the uncertainty and even the moments of doubt doesn't necessarily mean something is wrong. I didn't understand that it was actually indicators that I was being introduced to a new level of complexity that I didn't have time to internalize yet.&lt;/p&gt;

&lt;p&gt;You're not expected to walk into an existing system and immediately operate with the same level of context as someone who's been contributing to it for years. That expectation only exists if you place it on yourself. What's actually expected of you is the ability to learn, observe, ask questions and gradually build an understanding over time.&lt;/p&gt;

&lt;p&gt;The shift for me came when I stopped asking myself whether I fully understood everything that was happening around me and started asking a much simpler question like, do I understand more today than I did yesterday? That reframing allowed me to see progress in smaller, more realistic increments. A concept that felt completely unfamiliar one week, would start to make partial sense the next and eventually it became something I could explain or apply.&lt;/p&gt;

&lt;p&gt;That shift didn't remove the challenge, but it made it manageable and over time, my small increments of progress compounded to give birth to confidence.&lt;/p&gt;

&lt;p&gt;&lt;a id="Manager"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Establishing Clarity Through Your Manager
&lt;/h2&gt;

&lt;p&gt;One of the biggest mistakes I made early was underestimating how important my relationship with my manager was during that ramp-up period. I approached my 1-on-1 meetings the way I had approached check-ins in previous roles or environments, as something routine and almost procedural. I would show up, give a quick update on what I had been working on, mention anything that felt relevant and then move on. At the time, I thought I was doing what was expected but in reality, I was missing one of the most valuable opportunities available to me.&lt;/p&gt;

&lt;p&gt;I didn’t fully understand that those early conversations were one of the only spaces where I could access real context about how the team operated, what actually mattered and how I was being evaluated beyond surface level tasks. Without that context, I was making decisions in isolation, trying to determine what was important based on what I saw around me, rather than what was actually expected of me.&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%2Flui4biu81900kbh06g1r.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%2Flui4biu81900kbh06g1r.png" alt=" " width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That gap started to show up in subtle ways. I'd spend time going deeper in areas that felt important to me, but didn’t necessarily align with the team’s immediate priorities. I'd second guess whether I was moving fast enough, or focusing on the right things, because I didn’t have a clear benchmark to measure against. There was a lot of effort, but not much direction.&lt;/p&gt;

&lt;p&gt;A second shift happened when I started treating those 1-on-1 meetings as strategic conversations. I began coming in with intent, so instead of simply sharing what I'd done, I started asking more direct and at times, uncomfortable questions. &lt;/p&gt;

&lt;p&gt;I asked what success actually looked like in my first 30, 60 and 90 days, not in a general sense, but in the context of how my manager would evaluate my progress. I asked where new hires typically struggled so I could anticipate those challenges rather than react to them. I asked what I should be prioritizing right now and just as importantly, what I could afford to ignore without it negatively impacting my performance.&lt;/p&gt;

&lt;p&gt;Those questions changed everything!&lt;/p&gt;

&lt;p&gt;They gave me clarity that I couldn't have arrived at on my own, no matter how much I observed or how hard I worked. They provided a filter for my decision making. Instead of trying to do everything, I could focus on what actually mattered and instead of guessing whether I was on track, I had a clearer sense of how my progress was being perceived.&lt;/p&gt;

&lt;p&gt;What became clear is your manager operates with a level of visibility that you simply do not have as a new engineer. They understand how your work fits into the broader goals of the team, how performance is measured and where the real impact lies. Without tapping into that perspective, it's very easy to spend your time optimizing for things that feel productive but don't meaningfully move you forward.&lt;/p&gt;

&lt;p&gt;As you begin to use those meetings intentionally, they naturally evolve into a feedback loop. You bring your current approach, your questions and your assumptions into the conversation and your manager helps refine them. You get early signals on whether you're focusing on the right areas, whether your pace is appropriate and where you might need to adjust. That ability to course correct early is critical, especially in the first 90 days when your direction is still taking shape.&lt;/p&gt;

&lt;p&gt;Over time, you begin to build confidence in your understanding of what is expected of you. That alignment reduces a internal friction because instead of constantly questioning whether you're doing the right things, you're able to move forward with more clarity and intent.&lt;/p&gt;

&lt;p&gt;&lt;a id="Learning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning the System Before Trying to Prove Yourself
&lt;/h2&gt;

&lt;p&gt;There's a very natural instinct, especially early in your career, to want to prove that you belong. After all the effort it took to get the role, it feels like you need to validate that decision as quickly as possible so you try to contribute early by looking for opportunities to improve things and identifying patterns that seem inefficient or outdated based on what you’ve learned so far.&lt;/p&gt;

&lt;p&gt;I experienced this myself as I started getting more exposure to the codebase and the surrounding architecture, I began noticing decisions that didn’t fully align with what I had learned through courses, certifications or best practices. Certain implementations felt unconventional and some workflows didn’t look as streamlined as I expected. My initial reaction was to question whether these were things that needed to be fixed or optimized.&lt;/p&gt;

&lt;p&gt;But what I didn’t understand was that I was evaluating a real system through a theoretical lens.&lt;/p&gt;

&lt;p&gt;Over time, I started to realize what I was seeing was the result of real world constraints. Systems that exist in production environments are rarely built under ideal conditions. These systems are shaped by deadlines that had to be met, trade offs that had to be made, legacy decisions that still have downstream impact and in many cases, incidents that forced the team to adapt quickly in ways that may not look "clean" from the outside.&lt;/p&gt;

&lt;p&gt;So what appears inefficient without context often has a reason behind it. That reason may not be obvious in the code itself, but it exists in the history of how the system evolved.&lt;/p&gt;

&lt;p&gt;This is where my approach had to change. Instead of trying to evaluate the system based on what I thought it should be, I started focusing on understanding what it actually was. I became more intentional about asking why before forming an opinion. Why is this service structured this way? Why was this decision made? What problem was this solving at the time? What constraints influenced this approach?&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%2Fg9sb2j1ar9b5m3ekqgwd.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%2Fg9sb2j1ar9b5m3ekqgwd.png" alt=" " width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this mindset, I began spending more time tracing how requests moved through the system from entry point to response. I explored how infrastructure was defined and managed, whether through tools like CloudFormation or CDK and how those definitions translated into real environments. I paid closer attention to deployment workflows, how changes were reviewed and how they were safely released into production. I looked at logs and metrics to understand how the system behaved under different conditions, rather than just how it was intended to behave.&lt;/p&gt;

&lt;p&gt;In doing so, I started to see patterns that weren't obvious at first. I began to understand how different components interacted and why certain trade-offs were made. That level of understanding cannot be rushed and it cannot be replaced by external learning. It comes from spending time inside the system and allowing that context to build gradually.&lt;/p&gt;

&lt;p&gt;What followed was a noticeable shift in the quality of my contributions. When I eventually did suggest improvements or asked deeper questions, they were grounded in a clearer understanding of the system. They were not longer based on abstract best practices, but on how those practices applied or didn’t apply to the reality of the environment I was working in.&lt;/p&gt;

&lt;p&gt;There's also a level of credibility that comes with that. When you demonstrate that you've taken the time to understand before trying to change, your input is received differently. It shows respect for the work that has already been done and signals that your goal is to contribute in a meaningful way.&lt;/p&gt;

&lt;p&gt;&lt;a id="Depth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose Depth Over Breath to Narrow Your Focus
&lt;/h2&gt;

&lt;p&gt;Another challenge I faced early on was trying to learn too much at once. Coming from a self taught background, I had built my entire learning process around exploration. If there was a new service, I wanted to understand it, if there was a new tool gaining traction, I felt like I needed to at least be familiar with it. That approach served me well when I was trying to break into the industry, because exposure mattered. The more I saw, the more connections I could make and the more confident I became in navigating unfamiliar concepts.&lt;/p&gt;

&lt;p&gt;However, once I stepped into a real engineering role, that approach started to work against me.&lt;/p&gt;

&lt;p&gt;Instead of accelerating my progress, it was fragmented my attention. I would spend time learning tools and services that were interesting, but not directly relevant to the environment I was working in. I convinced myself that this would make me more prepared in the long run, but it was slowing down my ability to contribute in the short term. I was increasing my surface level knowledge but delaying the depth I needed to actually be effective on my team.&lt;/p&gt;

&lt;p&gt;This became more apparent when I compared what I was learning to what I was actually being asked to work on. There was a clear gap between the two. The work in front of me required a deeper understanding of a smaller set of tools, while my learning was spread across a much wider range of topics.&lt;/p&gt;

&lt;p&gt;I then decided to make a deliberate decision to narrow my focus to the environment I was operating in.&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%2Fd48kg1fl8bnfm5gy08ja.jpg" 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%2Fd48kg1fl8bnfm5gy08ja.jpg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started by identifying the core components of my team’s stack. If observability was handled through CloudWatch, then that became my primary focus for understanding logs, metrics and alerting. If the services I was working with were written in Python, then I invested more time in becoming comfortable with that language, rather than trying to split my attention across others. If infrastructure was defined using CDK, then I focused on understanding how those tools were used within our specific workflows, rather than exploring alternative infrastructure approaches.&lt;/p&gt;

&lt;p&gt;This shift toward depth created immediate benefits as the concepts I was learning began to show up directly in my day-to-day work. I could follow conversations more easily and complete tasks with greater confidence because the knowledge I was building was directly applicable.&lt;/p&gt;

&lt;p&gt;There's also a compounding effect that comes with depth. As you go deeper into a specific tool or service, you begin to understand how it behaves in different scenarios, how it integrates with other components and its limitations. That level of understanding allows you to move faster and make better decisions, even within a relatively narrow scope.&lt;/p&gt;

&lt;p&gt;This is not an argument against breadth in the long term. Expanding your knowledge across different tools and services is valuable and over time, it contributes to your ability to think more broadly about system design and architecture. However, timing matters! In the first 90 days, your priority is to become effective within the environment you're in.&lt;/p&gt;

&lt;p&gt;That requires a level of focus that can feel counterintuitive, especially if you're used to learning widely. It may feel like you're limiting yourself by not exploring everything at once but really, you're accelerating your ability to contribute by aligning your learning with what is immediately relevant.&lt;/p&gt;

&lt;p&gt;There'll always be time to expand later. Tools and technology aren't  going anywhere and your capacity to learn will only improve as you gain more experience. However, in those early stages, depth is what allows you to build momentum in transforming your learning from something abstract into practical.&lt;/p&gt;

&lt;p&gt;&lt;a id="Codebase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Codebase Is Where Everything Comes Together
&lt;/h2&gt;

&lt;p&gt;No course, certification, or tutorial fully will adequately prepare you for what you learn by working through a real codebase. Structured learning environments are designed to teach concepts in isolation, they give you clean examples, controlled scenarios and predictable outcomes, which are necessary when you're building foundational knowledge but production systems don't operate in isolation and they're rarely clean in the way learning environments present them.&lt;/p&gt;

&lt;p&gt;I remember the first time I intentionally tried to trace how a request moved through the system I was working on. I expected it to resemble the diagrams I had studied, where a request enters, flows through clearly defined components and returns a response in a way that is easy to follow. What I encountered instead was far more complex. The flow required jumping across multiple services, understanding how different components communicated with each other, and piecing together the path step by step. There were layers of abstraction, integrations I hadn’t seen before and behaviors that only made sense once I looked at them in context.&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%2F1szuvvaku67nqk8z3txh.webp" 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%2F1szuvvaku67nqk8z3txh.webp" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, it felt like I was constantly losing the thread of what I was trying to follow. I would start in one part of the system, only to realize that the logic I was looking for existed somewhere else entirely. It required patience to stay with the process and resist the urge to simplify what I was seeing into something more familiar.&lt;/p&gt;

&lt;p&gt;However, as I continued to spend time in the codebase, I started to see how the different layers of the system interacted. Infrastructure definitions began to make more sense when I saw how they supported the application logic. Observability became more meaningful when I connected logs and metrics back to actual execution paths. I finally began to understand how everything functioned collectively as part of a larger system.&lt;/p&gt;

&lt;p&gt;Patterns began to emerge and I started to recognize how certain types of problems were approached within my team. I saw recurring structures in how services were built, how errors were handled and how data flowed through the system. That pattern recognition is what allows me to move more confidently because I was no longer encountering everything as completely new.&lt;/p&gt;

&lt;p&gt;It's not always the most comfortable form of learning and it often requires sitting with confusion longer than'd prefer but that discomfort is part of the process. The more time you invest in understanding the system directly, the faster you transition from trying to piece things together to actually navigating the system with intent.&lt;/p&gt;

&lt;p&gt;&lt;a id="Relationships"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Relationships Will Accelerate Your Growth More Than You Expect
&lt;/h2&gt;

&lt;p&gt;One of the most underestimated aspects of your first 90 days is how much your growth is influenced by the people around you. When you're new to a role, it's easy to believe that your success will be determined primarily by how quickly you learn the technology, how well you write code, or how efficiently you complete tasks. While those things are important, they're only part of the equation. The environment you're stepping into is inherently collaborative and your ability to navigate that environment is closely tied to the relationships you build within it.&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%2Ff2b0arpgmnkt18i2bhw1.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%2Ff2b0arpgmnkt18i2bhw1.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Early in my career, I made a conscious decision to go beyond purely task based interactions with my teammates. Instead of limiting conversations to stand ups, tickets and code reviews, I began scheduling time to connect with people individually. These were't formal meetings but simple conversations aimed at understanding what each person worked on, how they approached problems and what their experiences had been within the team and the organization.&lt;/p&gt;

&lt;p&gt;At first, it felt like an extra effort on top of everything else I was trying to manage. There's always a tendency to prioritize what feels immediately productive and relationship building doesn't always show immediate results but over time, those conversations proved to be some of the most valuable investments I made during that period.&lt;/p&gt;

&lt;p&gt;They gave me insights that no documentation or onboarding material could provide. I learned how different engineers thought about trade-offs, how they approached debugging and how they navigated ambiguity. I gained context about why certain decisions were made and how different parts of the system evolved over time. These were perspectives that couldn't be captured in a runbook or a design document, but they were critical to understanding how to operate effectively within the team.&lt;/p&gt;

&lt;p&gt;Those relationships also changed how I experienced moments of uncertainty. When you're new, there will be times when you're stuck, whether it's due to a technical issue or a lack of context. Without established relationships, asking for help can feel like an interruption. If you hesitate and try to figure everything out on your own, in the process you'll lose time and momentum.&lt;/p&gt;

&lt;p&gt;Once I had built connections with my teammates, reaching out felt more like a continuation of an existing conversation as it felt like I was collaborating with someone I already knew. That reduced friction made it easier to ask questions earlier, unblock myself faster and learn more effectively from the people around me.&lt;/p&gt;

&lt;p&gt;Building that trust with teammates takes time, but the foundation can be established early. It comes from showing genuine interest in others’ work, being present in conversations and consistently engaging in a way that signals respect and curiosity.&lt;/p&gt;

&lt;p&gt;Another important aspect of relationship building is extending your network beyond your immediate team. As you begin to understand how your team operates, you'll also start to see how it connects with other teams and functions within the organization. Product managers, security teams, site reliability engineers and other engineering teams all play a role in the systems you're working on. Taking the time to understand how these groups operate and how your work intersects with theirs provides a broader perspective on the impact of what you're doing.&lt;/p&gt;

&lt;p&gt;These cross-functional relationships become increasingly valuable as you take on more complex work. They provide additional sources of context, open up opportunities for collaboration and make it easier to navigate dependencies that extend beyond your immediate team.&lt;/p&gt;

&lt;p&gt;Those relationships you build during your first 90 days create a support system that accelerates everything else you are trying to do.&lt;/p&gt;

&lt;p&gt;&lt;a id="90Days"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Strong First 90 Days Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;At the end of your first 90 days, there's an unspoken expectation that by this point you should feel fully confident, fully capable and fully independent in your role, but that's not how growth in engineering environments works. The first 90 days are about establishing direction as success during this period is better measured by the clarity you have developed and the momentum you have built.&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%2Fz0eu3atmfiyjd47z6npe.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%2Fz0eu3atmfiyjd47z6npe.png" alt=" " width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, you should have a solid sense of how work is prioritized, how tasks move from idea to implementation and how decisions are made within your team. This includes understanding the rhythm of your team’s processes, such as stand ups, sprint planning, code reviews and deployment workflows. By this stage, you should be able to navigate them with a level of confidence and awareness that allows you to participate more actively.&lt;/p&gt;

&lt;p&gt;In addition to process, clarity also extends to the technical environment you're working in. You should be familiar with the core tools and services that support your daily responsibilities. This doesn't mean you have mastered every detail, but you should understand how they're used within your team and how they fit into the broader system.&lt;/p&gt;

&lt;p&gt;Another important marker is your ability to navigate the codebase. Early on, the system may have felt fragmented and difficult to follow but now you should be able to trace key workflows with greater confidence. You should understand where to look when you're assigned a task, how different components connect and how changes move through the system so you can contribute meaningfully without feeling lost at every step.&lt;/p&gt;

&lt;p&gt;Also, by this stage, you should've established connections with your immediate team and have a working familiarity with the individuals you collaborate with regularly. These relationships should make it easier to ask questions, share ideas and navigate challenges.&lt;/p&gt;

&lt;p&gt;Alignment with your manager is now a critical component. You should have a clear understanding of what is expected of you moving forward, how your performance is being evaluated and where you should be focusing your efforts in the next phase of your role. This removes much of the uncertainty that exists early on and allows you to move forward with greater intention.&lt;/p&gt;

&lt;p&gt;At the end of 90 days is where momentum begins to build. The initial friction that once slowed you down should have started to decrease and your ability to move through problems becomes more fluid. Yes, at this stage you're still learning, but now you're learning from a position with context.&lt;/p&gt;

&lt;p&gt;&lt;a id="Conclusion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Conclusion
&lt;/h2&gt;

&lt;p&gt;The first 90 days of your career as developer will challenge you in ways that'll difficult to fully anticipate. It's a test of how you handle uncertainty, how you adapt to unfamiliar environments and how willing you're to stay committed to the learning process even when progress doesn't feel immediate.&lt;/p&gt;

&lt;p&gt;I came close to walking away from my first role because I misunderstood what that experience was supposed to feel like. I interpreted the discomfort, the confusion and the constant exposure to things I didn’t yet understand as signs that I wasn’t ready but in reality, those were all indicators that I was exactly where I needed to be, learning in an environment that was pushing me to grow.&lt;/p&gt;

&lt;p&gt;If you can approach this period with patience and intentional focus, you'll also notice the shift. Remember, have grace for yourself and allow yourself the space to grow into the role you've already earned.&lt;/p&gt;

&lt;p&gt;Be the engineer you're capable of being.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>codenewbie</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Amazon S3 Files Is Still Not A File System</title>
      <dc:creator>Ifeanyi O.</dc:creator>
      <pubDate>Thu, 09 Apr 2026 21:24:02 +0000</pubDate>
      <link>https://dev.to/aws/amazon-s3-files-is-still-not-a-file-system-28g5</link>
      <guid>https://dev.to/aws/amazon-s3-files-is-still-not-a-file-system-28g5</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;What is S3 Files&lt;/li&gt;
&lt;li&gt;What Changed for Developers&lt;/li&gt;
&lt;li&gt;How S3 Files Works at a High Level&lt;/li&gt;
&lt;li&gt;Why This Matters for AI&lt;/li&gt;
&lt;li&gt;Practical Code Example&lt;/li&gt;
&lt;li&gt;Security Operations&lt;/li&gt;
&lt;li&gt;Key Takeaways&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="Intro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;If you've spent any real time learning AWS, one of the first storage lessons you probably learned was Amazon S3 is not a file system. &lt;/p&gt;

&lt;p&gt;And that mattered because it explained a lot of the weirdness you'd run into early on that might have you asking...&lt;/p&gt;

&lt;p&gt;Why can't I just mount S3 like a normal shared drive?&lt;br&gt;
Why can't my application treat S3 data like regular files?&lt;/p&gt;

&lt;p&gt;But the answer has always been... S3 is object storage and even though that's obvious, it's a critical distinction because as interesting as S3 Files is, it seems to be confusing a lot of people that only &lt;a href="https://aws.amazon.com/blogs/aws/launching-s3-files-making-s3-buckets-accessible-as-file-systems/" rel="noopener noreferrer"&gt;read headlines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So no... S3 did not suddenly turn into a file system.&lt;/p&gt;

&lt;p&gt;&lt;a id="S3Files"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  So what is S3 Files?
&lt;/h2&gt;

&lt;p&gt;S3 Files is a file system interface for data that lives in S3 and connects AWS compute resources directly with data in S3. It gives applications file system access without the data ever leaving S3 and maintains a view of the objects in the bucket while translating file system operations into efficient S3 requests.&lt;/p&gt;

&lt;p&gt;Personally, the simple way to think about S3 Files is S3 remains the storage layer, S3 Files becomes the file-access layer and your apps sees files and directories.&lt;/p&gt;

&lt;p&gt;&lt;a id="Changes"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What changed for developers
&lt;/h2&gt;

&lt;p&gt;Before S3 Files, many workloads had a choice to make.&lt;/p&gt;

&lt;p&gt;Do you optimize for S3's scalability, durability and cost characteristics, or do you optimize for file system behavior that your applications already understand?&lt;/p&gt;

&lt;p&gt;S3 Files aims to remove that tradeoff by making general purpose S3 buckets accessible as native file systems for AWS compute resources and supports NFS v4.1+ file operations like create, read, update and delete.&lt;/p&gt;

&lt;p&gt;This is kind of a big deal because it means more workloads can work against data where it already lives instead of forcing you to move it somewhere else first.&lt;/p&gt;

&lt;p&gt;&lt;a id="Highlevel"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How S3 Files works at a high level
&lt;/h2&gt;

&lt;p&gt;At a high level, S3 Files creates a file system view over an S3 bucket.&lt;/p&gt;

&lt;p&gt;Your compute resource connects to that file system through a mount target in your VPC. For example, you can create the S3 file system, discover the mount target and then mount it from an EC2 instance using the &lt;code&gt;s3files&lt;/code&gt; file system type.&lt;/p&gt;

&lt;p&gt;Once mounted, your application can interact with the mounted path using normal file operations.&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;sudo mkdir&lt;/span&gt; /home/ec2-user/s3files
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; s3files fs-1234567890abcdef:/ /home/ec2-user/s3files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you can do familiar things like:&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello S3 Files"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /home/ec2-user/s3files/hello.txt
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-al&lt;/span&gt; /home/ec2-user/s3files/hello.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you create a file through the mounted file system, the file appears in the S3 bucket as an object and the contents remain the same when retrieved through the S3 API.&lt;/p&gt;

&lt;p&gt;That is the key idea in action and even thought you're working through the file interface, S3 still stores the data underneath.&lt;/p&gt;

&lt;p&gt;&lt;a id="AI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for AI
&lt;/h2&gt;

&lt;p&gt;S3 Files is clearly positioned for agents, machine learning and collaborative data-heavy workloads.&lt;/p&gt;

&lt;p&gt;The announcement page specifically calls out file-based applications, agents and ML teams as beneficiaries. It states that AI agents can persist memory and share state across pipelines, ML teams can run data preparation workloads without duplicating or staging files first and thousands of compute resources can connect to the same S3 file system simultaneously.&lt;/p&gt;

&lt;p&gt;That makes sense.&lt;/p&gt;

&lt;p&gt;A lot of modern AI and ML tooling still behaves in very file-centric ways. Training inputs, checkpoints, logs, intermediate artifacts and tool-driven workflows often assume files and directories are available. Even when your long-term storage strategy is object-first, the workloads themselves may still be file-first.&lt;/p&gt;

&lt;p&gt;&lt;a id="Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical code example
&lt;/h2&gt;

&lt;p&gt;Here's a simple way to show the difference conceptually:&lt;/p&gt;

&lt;p&gt;Let's look at working directly with S3 objects in Python.&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;boto3&lt;/span&gt;
&lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-data-bucket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reports/summary.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works fine, but your code is explicitly written around the S3 API model.&lt;/p&gt;

&lt;p&gt;Now let's review working with a mounted S3 Files path.&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="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/mnt/s3files/reports/summary.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second version feels ordinary because it is ordinary from the application's point of view.&lt;/p&gt;

&lt;p&gt;&lt;a id="Security"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Security and operational details worth noting
&lt;/h2&gt;

&lt;p&gt;S3 Files integrates with IAM for access control, supports identity and resource policies at both the file system and object level, encrypts data in transit with TLS 1.3 and supports encryption at rest with SSE-S3 or customer-managed AWS KMS keys. It can also monitor it using CloudWatch metrics and CloudTrail management events.&lt;/p&gt;

&lt;p&gt;So we can treat this as a real production service with access control, encryption and observability expectations teams will need.&lt;/p&gt;

&lt;p&gt;&lt;a id="Take"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The biggest takeaway is that the boundary between object storage workflows and file-based workflows has got much easier to work across.&lt;/p&gt;

&lt;p&gt;That matters because a lot of cloud architecture pain comes from interfaces not matching reality forces teams to build adapters, stage pipelines, duplicate storage systems and synchronize logic just to keep things moving.&lt;/p&gt;

&lt;p&gt;S3 Files now gives you the option to say, "maybe I shouldn't have to do that nearly as often."&lt;/p&gt;

&lt;p&gt;Lastly, if you're looking to dive deeper in your learning journey, explore these FREE AWS resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/6QPAC2M1HT/amazon-s3-files-native-file-system-access-for-your-s3-data/VTHPM94CZ4?trk=e3f50ee1-3e9a-412b-b5ed-61c3791a9fba&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to Amazon S3 Files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/free?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Free Tier Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://builder.aws.com/start?trk=e3f50ee1-3e9a-412b-b5ed-61c3791a9fba&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Builder Center Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;If you've got this far, thanks for reading! I hope it was worthwhile.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>5 AWS Services New Developers Struggle With (And Why)</title>
      <dc:creator>Ifeanyi O.</dc:creator>
      <pubDate>Tue, 07 Apr 2026 10:25:45 +0000</pubDate>
      <link>https://dev.to/aws/5-aws-services-new-developers-struggle-with-and-why-49a3</link>
      <guid>https://dev.to/aws/5-aws-services-new-developers-struggle-with-and-why-49a3</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;Identity and Access Management&lt;/li&gt;
&lt;li&gt;Virtual Private Cloud&lt;/li&gt;
&lt;li&gt;Simple Queue Service Vs Simple Notification Service&lt;/li&gt;
&lt;li&gt;CloudFormation&lt;/li&gt;
&lt;li&gt;CloudWatch&lt;/li&gt;
&lt;li&gt;Why These Services Matter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="Intro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Okay... let's be honest for a second.&lt;/p&gt;

&lt;p&gt;When you first opened the AWS Console, which service made you pause a little longer than the others? And I don't mean in a curious way but in a “wait… what the heck is actually going on here?” kind of way.&lt;/p&gt;

&lt;p&gt;AWS is extremely powerful and that’s part of the appeal. But with great power and limited context, you can feel overwhelmed, especially when you’re no longer working in a personal account. &lt;/p&gt;

&lt;p&gt;Yes, there are over 200 AWS services and most teams will rely heavily on a small subset but there are a select few that almost every new developer runs into early on and quietly struggles with. &lt;/p&gt;

&lt;p&gt;It's usually not because they’re innately complex to understand, but because they require a mental shift most new developers haven’t made yet.&lt;/p&gt;

&lt;p&gt;In this blog, we'll address five AWS services new developers struggle with which includes, &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Identity and Access Management (IAM)&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Virtual Private Cloud (VPC)&lt;/a&gt;, knowing the difference between &lt;a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-getting-started.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Simple Queue Service (SQS)&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/sns/latest/dg/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Simple Notification Service (SNS)&lt;/a&gt; and when to use which, &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CloudFormation&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon CloudWatch&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a id="IAM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  IAM
&lt;/h2&gt;

&lt;p&gt;AWS Identity and Access Management is the control plane gatekeeper. Every action performed in AWS eventually becomes an API call and every API call is evaluated by the IAM policy engine before it is allowed to proceed.&lt;/p&gt;

&lt;p&gt;This is where new developers first encounter friction because IAM is deterministic but not always obvious. When you receive an &lt;code&gt;AccessDenied&lt;/code&gt; error, this is the result of a precise evaluation process that has determined the request should not be allowed.&lt;/p&gt;

&lt;p&gt;When a request is made, AWS evaluates the principal making the request, the action being requested, the resource being accessed and any conditions that apply. That principal could be an IAM user, an assumed role, a federated identity, or a service role attached to a resources like an AWS Lambda function or Amazon EC2 instance. Developers often forget that once code runs in AWS, it is no longer acting as "you" but actually acting as the role attached to the compute resource.&lt;/p&gt;

&lt;p&gt;IAM evaluation considers identity-based policies attached to the principal, resource-based policies attached to the target resource, permission boundaries that may restrict the maximum allowed permissions of that principal and Service Control Policies (SCP) applied at the organizational level. If any applicable policy contains an explicit deny that matches the request, the request fails immediately, even if other policies allow it.&lt;/p&gt;

&lt;p&gt;This layered evaluation model is what confuses many developers. A developer may attach a policy granting permission to read from an S3 bucket, but the bucket policy may restrict access to requests originating from a specific VPC endpoint, or the organization may enforce an SCP preventing certain API calls entirely, or the role being assumed in a CI/CD pipeline may not include the permissions the developer tested locally.&lt;/p&gt;

&lt;p&gt;To make this more concrete, let's consider a simple identity-based policy that allows reading from an S3 bucket:&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;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::my-app-bucket/*"&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;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;At a glance, this policy appears sufficient as it allows the required action on the expected resource. However, IAM does not evaluate this policy in isolation. If a bucket policy restricts access to a specific network path, or an organizational policy blocks the action entirely, or the request is coming from a different role than expected, the final decision may still be a denial. The presence of an allow statement does not guarantee access if another layer introduces a conflicting rule.&lt;/p&gt;

&lt;p&gt;IAM also introduces conditional logic. Access can be restricted based on IP address, multi-factor authentication presence, encryption state, resource tags, or request context. Two seemingly identical API calls can produce different results based on environment.&lt;/p&gt;

&lt;p&gt;Let's review this updated identity-based policy that introduces an additional requirement:&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;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::my-app-bucket/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&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;"Bool"&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:SecureTransport"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&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;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;The same request will succeed or fail depending on whether it is made over HTTPS.&lt;/p&gt;

&lt;p&gt;For most developers, what makes IAM difficult early is that it forces you to think like a policy engine and start asking questions like, “Which principal is making this request and which policies are being evaluated?”&lt;/p&gt;

&lt;p&gt;However, once you understand the deterministic evaluation system of IAM policies, your debugging episodes will become more systematic and efficient.&lt;/p&gt;

&lt;p&gt;&lt;a id="VPC"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VPC
&lt;/h2&gt;

&lt;p&gt;Many developers don’t think deeply about networking early in their careers. Things usually just connect locally, APIs call databases and everything just works. However, when you join an actual team and start hearing phrases like, “It's in a private subnet,” or “The security group won’t allow that traffic,” or “There’s no route to the NAT gateway,” that's when you realize your lack of depth in cloud networking concepts and resources.&lt;/p&gt;

&lt;p&gt;For understanding, a VPC defines the networking boundaries of your AWS environment. It determines which resources are public, which are private, how traffic flows and what is allowed to communicate with what. Subnets, route tables, internet gateways, NAT gateways, security groups and network ACLs all play a role.&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%2Fegvtqzqoxub4fx3rel2h.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%2Fegvtqzqoxub4fx3rel2h.png" alt=" " width="581" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason new developers struggle with VPC is that networking is often abstracted until things begin to fail. You might deploy a Lambda function and wonder why it can’t connect to a database. Both the function and the database exists but if they’re in different subnets without proper routing or security group rules, they might as well be on separate planets.&lt;/p&gt;

&lt;p&gt;On AWS, connectivity explicit. Just because two resources exist does not mean they automatically can talk to each other. Traffic MUST be intentionally allowed.&lt;/p&gt;

&lt;p&gt;Let's consider what happens when a resource needs internet access from a private subnet. That path does not exist by default and must be explicitly defined through routing.&lt;/p&gt;

&lt;p&gt;Below is an example of a route table entry that allows traffic from a subnet to reach the internet through a NAT Gateway:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination: 0.0.0.0/0
Target: nat-0abc123example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single route determines whether instances in that subnet can reach external services like APIs, package repositories, or external databases. Without it, outbound traffic has nowhere to go, even if everything else appears to be configured correctly.&lt;/p&gt;

&lt;p&gt;Similarly, security groups act as virtual firewalls at the resource level. Even if routing is correct, traffic can still be blocked if the security group does not explicitly allow it.&lt;/p&gt;

&lt;p&gt;For example, a database security group might only allow inbound traffic on port 5432 from a specific application security group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: PostgreSQL
Port: 5432
Source: sg-0appserver123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, even if another resource is in the same VPC and subnet, it will not be able to connect unless it is associated with the allowed security group so connectivity cannot be assumed. It has to be defined.&lt;/p&gt;

&lt;p&gt;As a developer trying to grasp networking on AWS, at first, it might feel like a maze with invisible walls... and that's okay. Once you start visualizing the path a request takes, from the client through a load balancer, into a subnet, through a security group and into a database, understanding VPC will become easier to reason about.&lt;/p&gt;

&lt;p&gt;&lt;a id="SQSvsSNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SQS vs SNS
&lt;/h2&gt;

&lt;p&gt;Almost every new developer gets confused by Amazon SQS and Amazon SNS at some point. They both move messages, are used in event-driven systems and are often mentioned together in architectural diagrams. So the question is... what’s the difference?&lt;/p&gt;

&lt;p&gt;For starters, Amazon SQS is basically a queue. Messages sit there until something pulls them and processes them. On the contrary, Amazon SNS is a publish-and-subscribe service where messages are pushed to subscribers when they are published.&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%2F0bm83dn9wj3dd668nhyt.webp" 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%2F0bm83dn9wj3dd668nhyt.webp" alt=" " width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This sounds simple, but the confusion comes from how they’re used together. You’ll see architectures where an S3 event triggers an SNS topic, which then fans out to multiple SQS queues, then trigger Lambda functions or you’ll see an SNS topic directly invoking endpoints and maybe EventBridge involved somewhere in the mix. As more services are integrated, suddenly, the flow of data feels less obvious.&lt;/p&gt;

&lt;p&gt;Let's review what it looks like to publish a message to an SNS topic:&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;boto3&lt;/span&gt;

&lt;span class="n"&gt;sns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sns&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TopicArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;arn:aws:sns:us-east-1:123456789012:my-topic&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Order created&lt;/span&gt;&lt;span class="sh"&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 moment this message is published, SNS immediately pushes it to all of its subscribers. That could include multiple SQS queues, Lambda functions, or even HTTP endpoints. The publisher does not need to know who those subscribers are, it simply emits the event.&lt;/p&gt;

&lt;p&gt;Now compare that to SQS. Messages are not pushed to consumers, they remain in the queue until something explicitly retrieves (pulls) them:&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;boto3&lt;/span&gt;

&lt;span class="n"&gt;sqs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sqs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;QueueUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://sqs.us-east-1.amazonaws.com/123456789012/my-queue&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MaxNumberOfMessages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the consumer is responsible for polling the queue, retrieving messages and processing them. If no consumer is running, the message simply stays in the queue.&lt;/p&gt;

&lt;p&gt;The real struggle here is not in the intricacies of the syntax of the services, it's more about the architectural thinking that's require here. You have to ask questions like, "Do I need multiple consumers?", "Do I need messages to persist until they’re processed?", "What happens if a consumer fails?", "Will this message be retried?", "Could it be processed twice?" and this is where the distinction becomes meaningful. &lt;/p&gt;

&lt;p&gt;SQS gives you durability and control over processing. Messages persist until they are handled, which makes it useful when you need reliability and buffering between systems. SNS gives you immediacy and fan-out. It is designed to broadcast events to multiple systems at once without tightly coupling them.&lt;/p&gt;

&lt;p&gt;Additionally, messaging introduces distributed systems concepts like at-least-once delivery and idempotency. For many developers, this is the first time they have to think beyond simple request-response patterns like when a message may be delivered more than once, a consumer may fail mid-processing, or systems may process events at different speeds.&lt;/p&gt;

&lt;p&gt;This is how SQS and SNS can feel confusing complex early because the real challenge is understanding how they behave when systems are no longer tightly connected and operations don't happen in a single request-response cycle.&lt;/p&gt;

&lt;p&gt;&lt;a id="CloudFormation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CloudFormation
&lt;/h2&gt;

&lt;p&gt;At some point, you’ll try to modify a resource in the AWS Console and get a message telling you that the resource is managed by CloudFormation and that's you'll realize that you’re interacting with infrastructure defined as code.&lt;/p&gt;

&lt;p&gt;AWS CloudFormation allows teams to define infrastructure in templates and deploy it as stacks and those stacks become the source of truth. If something is defined in a template, manual console changes are temporary at best and overwritten at worst.&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%2Ftv3covfpwddpclv8ttjn.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%2Ftv3covfpwddpclv8ttjn.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;New developers struggle here because it requires discipline and patience. You can’t just click and tweak something quickly, you need to find the template, understand how the resource is defined, update it properly and redeploy the stack. Additionally, when a stack update fails, the error messages can be intimidating.&lt;/p&gt;

&lt;p&gt;Let's look at a simple CloudFormation template that defines an S3 bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MyBucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::S3::Bucket&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;BucketName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app-bucket-123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This template does not describe how to create the bucket step by step. Instead, it defines that a bucket with this name, &lt;code&gt;my-app-bucket-123&lt;/code&gt;, should exist. When deployed, CloudFormation creates and manages that resource as part of a stack.&lt;/p&gt;

&lt;p&gt;If you later change the bucket name in the template and redeploy, CloudFormation will determine what needs to change to match the new desired state. That might mean replacing the resource entirely, which is why understanding updates is just as important as initial creation.&lt;/p&gt;

&lt;p&gt;CloudFormation forces you to think declaratively. Instead of saying, “Create this resource,” you define the desired state and let AWS reconcile the difference. It’s a powerful approach, but it changes how you work. It also means most of what you’re touching likely existed before you arrived and was created intentionally through code.&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%2Fisg1a36tfwodr66wccgm.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%2Fisg1a36tfwodr66wccgm.png" alt=" " width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;New developers have to intentionally learn to stop treating the console as the place to make changes and start treating CloudFormation templates as the source of truth. Once you understand that every update goes through the stack, even when something fails, you'll know where to look to fix it.&lt;/p&gt;

&lt;p&gt;&lt;a id="CloudWatch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CloudWatch
&lt;/h2&gt;

&lt;p&gt;As a new developer, you'll be focusing on building features so observability can sometimes feel like a secondary task. However, the minute something breaks in production, then suddenly logs and metrics are all anyone cares about.&lt;/p&gt;

&lt;p&gt;Amazon CloudWatch is where you go to understand what your systems are actually doing in real time as it handles logs, metrics, alarms and dashboards but it does not interpret the data for you. What you get is raw signals that you have to make sense of them.&lt;/p&gt;

&lt;p&gt;You might open a log group and scroll through hundreds of lines without knowing what you’re looking for, or see a metric spike but not know what "normal" even looks like, or even wonder why an alarm didn’t trigger when you expected it to.&lt;/p&gt;

&lt;p&gt;Let's look at what a simple log entry from a Lambda function might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-03-31T14:22:10.123Z  ERROR  Failed to process orderId=12345
Traceback (most recent call last):
  File "/var/task/app.py", line 42, in handler
    process_order(order)
Exception: Database connection timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At a glance, this tells you something failed, but in a distributed system, this is rarely the full story. The database might be in a different subnet, behind a security group, or experiencing latency issues, so the log gives you a clue, but it's not the complete answer.&lt;/p&gt;

&lt;p&gt;Now consider a metric that tracks errors over time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;Metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Errors&lt;/span&gt;
&lt;span class="py"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS/Lambda&lt;/span&gt;
&lt;span class="py"&gt;Statistic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sum&lt;/span&gt;
&lt;span class="py"&gt;Period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5 minutes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this metric spikes, CloudWatch can trigger an alarm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;Alarm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LambdaErrorAlarm&lt;/span&gt;
&lt;span class="py"&gt;Threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Errors &amp;gt; 5&lt;/span&gt;
&lt;span class="err"&gt;Evaluation&lt;/span&gt; &lt;span class="py"&gt;Period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1 datapoint&lt;/span&gt;
&lt;span class="py"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send notification to SNS topic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even here, interpretation is required. Is five errors in five minutes abnormal? Is that a real issue or expected behavior during traffic spikes? CloudWatch provides the signal, but it does not define what is meaningful.&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%2Fqewspwd1ynif8cyv4s9a.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%2Fqewspwd1ynif8cyv4s9a.png" alt=" " width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The challenge here is that debugging in distributed systems is very different from debugging locally. There’s no single stack trace that tells the whole story and you have to piece together information across services.&lt;/p&gt;

&lt;p&gt;The good news is overtime, you will build intuition and learn which metrics matter, how to structure logs and when to create alarms. But early on, CloudWatch can feel overwhelming as it exposes the complexity of production systems in it's full detail.&lt;/p&gt;

&lt;p&gt;&lt;a id="Conclusion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why These Five Services Matter
&lt;/h2&gt;

&lt;p&gt;As a new developer, these five services show up early because they sit at the foundation of how systems are built and operated.&lt;/p&gt;

&lt;p&gt;IAM teaches you to think in terms of identity and authorization, VPC teaches you to understand network boundaries and traffic flow, SQS and SNS introduce you to distributed and event-driven thinking, CloudFormation forces you to respect infrastructure as code and existing systems and CloudWatch pushes you to think operationally and observe before you optimize.&lt;/p&gt;

&lt;p&gt;They represent transitions in how you think as a developer working in the cloud.&lt;/p&gt;

&lt;p&gt;If you’re struggling with one of them right now, don't worry. It’s usually a sign that you’re growing. Every developer who works seriously in AWS goes through a growing phase. The difference over time is that what once felt confusing will eventually become familiar.&lt;/p&gt;

&lt;p&gt;Lastly, if you're looking to dive deeper in your learning journey, explore these FREE AWS resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/free?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Free Tier Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://builder.aws.com/start?trk=e3f50ee1-3e9a-412b-b5ed-61c3791a9fba&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Builder Center Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/PH6Z6EVH8Z/introduction-to-amazon-virtual-private-cloud-vpc/PA8H7FUE15?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to Amazon VPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/XFPX3M7HAQ/introduction-to-aws-identity-and-access-management-iam/DQJ3N5QRRU?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to AWS IAM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/852GE321E4/aws-simple-queue-service-sqs-getting-started/BHE6AN97CN?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to Amazon SQS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/RD9AS2GJKC/amazon-simple-notification-service-sns-getting-started/KH9EY5CXS2?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to Amazon SNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/RH22P2RXU4/aws-cloudformation-getting-started/KEK5BT6HSE?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to AWS CloudFormation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/HS1HSVQRHK/amazon-cloudwatch-getting-started/9Y34KP2H1T?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to Amazon CloudWatch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Good luck!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;If you've got this far, thanks for reading! I hope it was worthwhile.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>5 Common AWS Errors New Developers Hit (And How to Fix Them)</title>
      <dc:creator>Ifeanyi O.</dc:creator>
      <pubDate>Wed, 11 Mar 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/aws/5-common-aws-errors-new-developers-hit-and-how-to-fix-them-fkl</link>
      <guid>https://dev.to/aws/5-common-aws-errors-new-developers-hit-and-how-to-fix-them-fkl</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;AccessDenied&lt;/li&gt;
&lt;li&gt;InvalidClientTokenId&lt;/li&gt;
&lt;li&gt;ThrottlingException&lt;/li&gt;
&lt;li&gt;ResourceNotFoundException&lt;/li&gt;
&lt;li&gt;ValidationException&lt;/li&gt;
&lt;li&gt;Patterns Behind the Errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="Intro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;You take pride in writing clean code...&lt;br&gt;
You've passed all the technical interviews...&lt;br&gt;
You've shipped features locally without breaking anything...&lt;br&gt;
Then you attempt to deploy in a &lt;em&gt;real&lt;/em&gt; AWS environment, and quickly get humbled.&lt;/p&gt;

&lt;p&gt;If you’ve read &lt;a href="https://dev.to/aws/everything-you-need-to-know-about-aws-for-your-first-developer-job-52o2"&gt;my previous blog post&lt;/a&gt; about starting your first developer job in an AWS environment, then you know the moment I’m referring to. You log into the console at work and notice resources that existed long before you arrived, with names that look autogenerated and dashboards that are lighting up.&lt;/p&gt;

&lt;p&gt;Then after a few weeks of getting comfortable, you try to deploy a feature or call an API for the first time, and you're stopped in your tracks by an &lt;em&gt;AccessDenied&lt;/em&gt; error message.&lt;/p&gt;

&lt;p&gt;You feel confused at first because nothing seems obviously wrong. Your code runs, your logic is sound and yet AWS still tells you, "you can't pass through!". That's when you learn the lesson that AWS operates on very strict rules around identity, permissions, configuration, quotas, and validation. It is extremely literal so if something does not meet its expectations exactly, it will reject the request.&lt;/p&gt;

&lt;p&gt;Every developer, no matter how experienced, will stumble on AWS error messages so you're not going to avoid them entirely. However, in this blog, we're going to help you understanding what these error messages mean, how to both resolve them and reduce the chances of stumbling into them in the first place.&lt;/p&gt;

&lt;p&gt;Now let's walk through these 5 common errors messages, &lt;em&gt;AccessDenied&lt;/em&gt;, &lt;em&gt;InvalidClientTokenId&lt;/em&gt;, &lt;em&gt;ThrottlingException&lt;/em&gt;, &lt;em&gt;ResourceNotFoundException&lt;/em&gt; and &lt;em&gt;ValidationException&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id="AccessDenied"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  AccessDenied (Nope! You're not allowed to do that!)
&lt;/h2&gt;

&lt;p&gt;If there's one error message that will shape your first year working with AWS, it's the &lt;em&gt;AccessDenied&lt;/em&gt; error message.&lt;/p&gt;

&lt;p&gt;This error does not necessarily mean your code is syntactically wrong, or your logic is flawed. Actually, it means AWS fully understood what you asked it to do but intentionally rejected the request because your identity is not authorized to perform that action.&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%2Fc1lq55vcrquu1nd5kg6n.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%2Fc1lq55vcrquu1nd5kg6n.png" alt=" " width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of the time, this traces back to &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Identity and Access Management&lt;/a&gt;. You might be trying to read from an &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;S3&lt;/a&gt; bucket, or invoke a &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Lambda&lt;/a&gt; function, or attach a role to a resource, but the IAM principal you're currently operating as does not have permission to perform that specific API action on that specific resource. &lt;/p&gt;

&lt;p&gt;In more subtle cases, you might be in the wrong AWS account entirely, or targeting the wrong region and sometimes the missing permission is not obvious, such as &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_passrole.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;iam:PassRole&lt;/a&gt; when a service needs to assume a role on your behalf.&lt;/p&gt;

&lt;p&gt;When I first started working in &lt;em&gt;real&lt;/em&gt; AWS environments, I thought an &lt;em&gt;AccessDenied&lt;/em&gt; error message meant I'd made a personal mistake because I assumed I'd configured something incorrectly. Then, I later learned it was a deliberate guardrail my manager had set to limit what I could do in a specific AWS account, which was a good thing. In case you didn't know, most developers will never have full access to the AWS environment at their jobs. &lt;/p&gt;

&lt;p&gt;When resolving an AccessDenied error, your first step is to confirm that you’re actually supposed to have access. Once that’s clear, your next question should be, "who am I right now?" In AWS, access is entirely based on identity, so before you assume the problem is a missing permission, you need to verify which principal is actually making the request. One of the fastest ways to answer that question is to ask AWS directly using the AWS CLI in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command returns the account ID and &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;ARN&lt;/a&gt; of the user or role you’re currently authenticated as, immediately telling you whether you’re in the wrong AWS account, assuming an unexpected role, or using a different profile than you thought. &lt;/p&gt;

&lt;p&gt;From there, you can ask more specific questions like, "Am I using the correct IAM role?", "Am I authenticated through the expected &lt;a href="https://aws.amazon.com/what-is/sso/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;SSO&lt;/a&gt; profile?", or "Am I running this from my local machine, from a &lt;a href="https://aws.amazon.com/what-is/ci-cd-pipeline/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;CI/CD pipeline&lt;/a&gt; role, or from within a Lambda function?" Each of those execution contexts has a completely different permission set, and many &lt;em&gt;AccessDenied&lt;/em&gt; errors often result from operating in a context you didn’t intend.&lt;/p&gt;

&lt;p&gt;From a reactive standpoint, the fastest way to debug &lt;em&gt;AccessDenied&lt;/em&gt; error message is to read the full message carefully. AWS often includes the exact action that was denied and the ARN of the resource involved that tells you precisely which permission is missing. From there, you can inspect the attached IAM policies for your user or role and verify whether that action is allowed on that resource. If you're working in an organization with &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Service Control Policies&lt;/a&gt;, you may also need to check whether a higher-level restriction is blocking the action even if your local role appears correct.&lt;/p&gt;

&lt;p&gt;So how can we limit &lt;em&gt;AccessDenied&lt;/em&gt; errors so they don't slow you down? &lt;/p&gt;

&lt;p&gt;One practical way is to design with least privilege intentionally instead of retroactively. When you're creating a new role for a service, take a few extra minutes to identify exactly which API calls it will need and grant those explicitly. If you're using infrastructure as code, strive to define IAM policies alongside your compute resources so permissions evolve with your application rather than lag behind it.&lt;/p&gt;

&lt;p&gt;Another proactive habit is verifying your execution context before running critical operations. Make sure you get comfortable checking which AWS account and region you're currently in and confirming which IAM role your CLI profile or deployment pipeline is using because many &lt;em&gt;AccessDenied&lt;/em&gt; issues are a result of operating in an unexpected environment.&lt;/p&gt;

&lt;p&gt;&lt;a id="InvalidClientTokenId"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  InvalidClientTokenId (Yo! I don't know who you are)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;InvalidClientTokenId&lt;/em&gt; usually shows up when you're working with the CLI, an &lt;a href="https://aws.amazon.com/what-is/sdk/#what-is-an-sdk--1chu1sx?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;SDK&lt;/a&gt;, or running code from your local environment. At first glance, this error message reads like something is fundamentally broken, but in reality, it's really straight forward.&lt;/p&gt;

&lt;p&gt;It means the credentials attached to your request are either invalid, expired, or not the correct identity you think you're using.&lt;/p&gt;

&lt;p&gt;Every AWS request is cryptographically signed so when you authenticate, AWS provides credentials that allow you to generate a signature proving who you are. That signature includes your access key and a timestamp and if the token is expired, malformed, revoked, or tied to access a different account than expected, AWS rejects the request immediately before even checking permissions. In other words, this is not about what you're allowed to do but whether AWS trusts who you are.&lt;/p&gt;

&lt;p&gt;You’ll often see it surface in even the simplest SDK call:&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;boto3&lt;/span&gt;

&lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_buckets&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your credentials are expired or incorrect, AWS will respond with something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;An error occurred (InvalidClientTokenId) when calling the ListBuckets operation:
The security token included in the request is invalid.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that this happens before any permission evaluation because the request fails at the identity layer. &lt;/p&gt;

&lt;p&gt;Early in my career, I lost more time to this error than I want to admit. I would question my app logic, inspect config files, and re-run deployments but eventually, I realized that whenever AWS complains about tokens, client identity, or security credentials, the problem is almost always contextual.&lt;/p&gt;

&lt;p&gt;For a proactive debugging path, first confirm which AWS profile is currently active. If you're using AWS SSO, attempt to refresh your session. If you're using long-term credentials, confirm they haven't  been rotated or invalidated and check for environment variables such as &lt;em&gt;AWS_ACCESS_KEY_ID&lt;/em&gt;, &lt;em&gt;AWS_SECRET_ACCESS_KEY&lt;/em&gt;, or &lt;em&gt;AWS_PROFILE&lt;/em&gt; that may be overriding your expected configuration. If you're inside a container or CI/CD pipeline, verify which role is being assumed and whether it is still valid.&lt;/p&gt;

&lt;p&gt;Another common scenario, is accidentally switching accounts. You might have authenticated successfully, but into the wrong AWS account. From the perspective of AWS, your token is valid, but not for the resources you're trying to access.&lt;/p&gt;

&lt;p&gt;So before running critical commands, know exactly which identity you are operating as, be explicit about profiles instead of relying on defaults and in multi-account environments, make the current account visible in your prompt or logging output. As for CI/CD pipelines, try to surface the assumed role clearly in logs so it's not ambiguous which identity is making requests.&lt;/p&gt;

&lt;p&gt;Lastly, always keep in mind that credential lifetimes are temporary credentials designed to expire so you'll intentionally need to build your workflows around refreshing sessions and not assume they'll last indefinitely.&lt;/p&gt;

&lt;p&gt;&lt;a id="ThrottlingException"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ThrottlingException (Dude! Slow down!)
&lt;/h2&gt;

&lt;p&gt;When you see a &lt;em&gt;ThrottlingException&lt;/em&gt; or &lt;em&gt;TooManyRequestsException&lt;/em&gt; error message, understand that AWS is enforcing limits to prevent you from overwhelming a system.&lt;/p&gt;

&lt;p&gt;Every AWS service operates with defined quotas and internal protection mechanisms and these limits exist to preserve stability, fairness, and predictable performance across millions of customers. When your request rate exceeds what the service can handle at that moment for your account, AWS responds by throttling you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fep08eemciresh02pnidk.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%2Fep08eemciresh02pnidk.png" alt=" " width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;New developers often hit this error message unintentionally because it's easy to write code that scales requests unintentionally, like a  loop that calls an API hundreds of times per second or a Lambda function that scales concurrency faster than expected. In your local development, you rarely think about rate limits because everything runs in-process but in distributed systems, request pacing is an important part of the architecture.&lt;/p&gt;

&lt;p&gt;When a &lt;em&gt;ThrottlingException&lt;/em&gt; or &lt;em&gt;TooManyRequestsException&lt;/em&gt; error message appears, the first question to ask is whether the throttling is burst-based or sustained. If it resolves quickly, you likely experienced a short spike but if it persists consistently, you may be exceeding configured quotas or overloading a particular resource.&lt;/p&gt;

&lt;p&gt;The immediate instinct is often to retry immediately, but that can actually make the problem worse. The fix is to control retry logic using exponential backoff so requests slow down progressively instead of hammering the service. &lt;/p&gt;

&lt;p&gt;Most AWS SDKs include retry logic automatically, but you should understand how it works and configure it intentionally when necessary. For example, in Python using &lt;a href="https://aws.amazon.com/sdk-for-python/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Boto3&lt;/a&gt;, you can define retry behavior like this:&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;botocore.config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;retry_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_attempts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# or "adaptive"
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;dynamodb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dynamodb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;retry_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_tables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The standard mode applies exponential backoff, while adaptive adds client-side rate awareness. In short spikes, this can mean the difference between graceful recovery and cascading failure. When throttling persists consistently, however, it may indicate that you are exceeding a quota or that concurrency needs to be adjusted. Observability will play a critical role here for have visibility into what's actually happening. Some key metrics you'd want to monitor are, request counts, error rates, and service quotas so you understand whether you’re dealing with bursts or sustained pressure.&lt;/p&gt;

&lt;p&gt;&lt;a id="ResourceNotFoundException"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ResourceNotFoundException (That doesn’t exist. At least not here)
&lt;/h2&gt;

&lt;p&gt;Few things are more confusing than seeing a resource clearly visible in the AWS Console while your application insists it doesn’t exist. When you encounter a &lt;em&gt;ResourceNotFoundException&lt;/em&gt;, the instinct is often to assume AWS is contradicting itself. It usually isn’t.&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%2Fpp7o2qcoaatph8ndyrf5.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%2Fpp7o2qcoaatph8ndyrf5.png" alt=" " width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS resources are almost always scoped to a specific region and account. If your Lambda function lives in us-east-1 and your CLI or SDK is configured for us-west-2, AWS is absolutely correct when it says the resource does not exist, because it does not exist in that region. &lt;/p&gt;

&lt;p&gt;This is easy to miss in code. For example:&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;boto3&lt;/span&gt;

&lt;span class="n"&gt;lambda_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lambda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-west-2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lambda_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;FunctionName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-production-function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that function actually lives in us-east-1, this call will fail with &lt;em&gt;ResourceNotFoundException&lt;/em&gt;. Simply being explicit about region can eliminate ambiguity:&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="n"&gt;lambda_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lambda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&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 same applies to account boundaries. A resource in one AWS account is completely invisible to another unless explicitly shared through mechanisms like cross-account access.&lt;/p&gt;

&lt;p&gt;There are other subtle variations of this issue as well, for example, the ARN might be malformed or the resource ID contains a small typo. Other more nuanced causes are, a resource might been deleted and recreated with a slightly different identified or an application might be running in an execution context that doesn't have visibility into the resource even though it exists.&lt;/p&gt;

&lt;p&gt;When you encounter the &lt;em&gt;ResourceNotFoundException&lt;/em&gt; error message, resist the urge to immediately question AWS but instead, verify your context. Confirm the AWS account you're operating in, confirm the region config in your SDK or CLI, log the exact ARN or resource identifier being used in the request and check environment variables and configuration files to confirm they are pointing to the environment you expect.&lt;/p&gt;

&lt;p&gt;One of the fastest debugging tips here is printing out the region and account identity at application startup. When something fails, you want immediate clarity about where you're operating from. Many “missing resource” errors are simply requests being sent to the wrong environment.&lt;/p&gt;

&lt;p&gt;Additionally, try not to rely on defaults and ambiguous configurations that changes between development and production. In team environments, document which accounts and regions are responsible for which workloads and name resources in ways that make their environment obvious. When using multiple accounts, consider standardizing environment variables or deployment conventions so region and account targeting are always intentional.&lt;/p&gt;

&lt;p&gt;&lt;a id="ValidationException"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ValidationException (Your input doesn’t meet the rules!)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;ValidationException&lt;/em&gt; error messages show up across many AWS services and often feels frustrating because it can appear generic at first. However, they mean your request did not satisfy one or more of the service’s defined constraints.&lt;/p&gt;

&lt;p&gt;AWS APIs operate on contracts and every operation has required parameters, allowed values, length limits, formatting rules, and structural expectations. If any part of your request violates that contract, the service rejects it immediately.&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%2Ft2p6l4tdl8mwdgk9hja5.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%2Ft2p6l4tdl8mwdgk9hja5.png" alt=" " width="648" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This could mean a required field is missing or an ARN is malformed, a numeric value exceeds an allowed range or even something as subtle as incorrect casing in an enumerated value. For example, consider creating a &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;DynamoDB&lt;/a&gt; table:&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;boto3&lt;/span&gt;

&lt;span class="n"&gt;dynamodb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dynamodb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AttributeDefinitions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;userId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;STRING&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Incorrect value
&lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;KeySchema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;userId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;KeyType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HASH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;BillingMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PAY_PER_REQUEST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;STRING&lt;/code&gt; is invalid. DynamoDB expects &lt;code&gt;S&lt;/code&gt; for string types. That small mismatch causes a &lt;em&gt;ValidationException&lt;/em&gt; because the input does not match the expected schema.&lt;/p&gt;

&lt;p&gt;A common mistake new developers make is not slowing down enough to read what the error message is clearly telling them. AWS is usually very explicit about what went wrong, like whether a required field is missing, a value doesn’t match the expected pattern, a data type is incorrect, or a maximum length constraint was exceeded.&lt;/p&gt;

&lt;p&gt;To solve this error, you can examine the exact request being sent and compare it line by line with the official API documentation, confirm that required parameters are present and verify formats for ARNs and resource identifiers, double-check enum values and numeric limits and if you're using an SDK, log the final constructed request object to confirm it matches your expectations.&lt;/p&gt;

&lt;p&gt;I believe it's worth checking whether your configuration has been modified by environment variables or defaults that differ across environments. A configuration that works in development may fail in production if a required parameter is missing or structured differently.&lt;/p&gt;

&lt;p&gt;You should also treat infrastructure definitions and service configurations as strongly typed artifacts rather than loosely structured text. I strongly recommend using infrastructure-as-code tools that perform validation before deployment and linters or schema validation tools where possible to validate input early so malformed data never reaches AWS APIs.&lt;/p&gt;

&lt;p&gt;&lt;a id="Conclusion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Patterns Behind the Errors
&lt;/h2&gt;

&lt;p&gt;As a new developer at your job, you might feel like you're constantly unexpectedly running into AWS error messages, but understand that this is all part of becoming more experienced in the cloud. &lt;/p&gt;

&lt;p&gt;Overtime, you'll begin to notice that most error messages fall into the predictable categories of identity and authorization issues, permission boundaries, scope mismatches, validation failures, or scale constraints. &lt;/p&gt;

&lt;p&gt;As you gain experience, your debugging process will become much calmer and structured instead of reactive and scattered because you'll be able to classify error messages into one of those buckets within the first few seconds.&lt;/p&gt;

&lt;p&gt;I am curious to know though, which one of these AWS error messages trip you up the most or is the most frustrating to see?&lt;/p&gt;

&lt;p&gt;Lastly, if you're looking to dive deeper in your learning journey, explore these FREE AWS resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/free?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Free Tier Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://builder.aws.com/start?trk=e3f50ee1-3e9a-412b-b5ed-61c3791a9fba&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Builder Center Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://repost.aws?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS re:Post Q&amp;amp;A Community Knowledge Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/XFPX3M7HAQ/introduction-to-aws-identity-and-access-management-iam/DQJ3N5QRRU?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to Identity and Access Management (IAM)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/J59SS92GUN/aws-billing-and-cost-management/25JXE6WYAY?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to AWS Billing Services and Cost Management
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Good luck!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;If you've got this far, thanks for reading! I hope it was worthwhile.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>developer</category>
      <category>cloud</category>
      <category>security</category>
    </item>
    <item>
      <title>Everything You Need to Know About AWS for Your First Developer Job</title>
      <dc:creator>Ifeanyi O.</dc:creator>
      <pubDate>Tue, 10 Feb 2026 11:12:37 +0000</pubDate>
      <link>https://dev.to/aws/everything-you-need-to-know-about-aws-for-your-first-developer-job-52o2</link>
      <guid>https://dev.to/aws/everything-you-need-to-know-about-aws-for-your-first-developer-job-52o2</guid>
      <description>&lt;p&gt;&lt;em&gt;A real-world guide for day-one developers&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;Your First Surprise&lt;/li&gt;
&lt;li&gt;AWS Categories&lt;/li&gt;
&lt;li&gt;Your Terminal Is Important&lt;/li&gt;
&lt;li&gt;It Already Existed&lt;/li&gt;
&lt;li&gt;Think Serverless&lt;/li&gt;
&lt;li&gt;Changes in Prod&lt;/li&gt;
&lt;li&gt;Observe Before You Optimize&lt;/li&gt;
&lt;li&gt;Cost Will Show Up&lt;/li&gt;
&lt;li&gt;Structure from Certifications&lt;/li&gt;
&lt;li&gt;What Really Matters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="Intro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;You just landed your first developer job! Congratulations!&lt;/p&gt;

&lt;p&gt;You’re excited, proud and already imagining what it’ll be like to finally build things for real, not just for personal projects and experimentation.&lt;/p&gt;

&lt;p&gt;Day one comes around, you open your new company laptop, join a few team channels, and begin receiving access to an AWS account, or maybe several.&lt;/p&gt;

&lt;p&gt;You notice pipelines you didn’t create, services you recognize by name but not by behavior and permissions you don’t fully understand.&lt;/p&gt;

&lt;p&gt;You might even see things like &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon S3&lt;/a&gt; buckets, &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; functions, &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon API Gateway&lt;/a&gt; endpoints, &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon CloudWatch&lt;/a&gt; dashboards, and a few &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS IAM&lt;/a&gt; roles with names that look like they were created by someone in a hurry.&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%2F4we3esvb71fdntn4dj1z.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%2F4we3esvb71fdntn4dj1z.png" alt=" " width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s when it hits you. You didn’t actually know what to expect.&lt;/p&gt;

&lt;p&gt;You want to do well and increase the possibility of ramping up quickly to make a good impression and avoid being the person who breaks something important or feels lost for weeks. You start asking yourself, what should you already know, what should you focus on first, and how do people actually work with AWS day to day.&lt;/p&gt;

&lt;p&gt;Don’t worry, I’ve got you! This post is for that moment.&lt;/p&gt;

&lt;p&gt;This post is for developers preparing to start their first job working with AWS and trying to figure out how to be ready before and after day one. We’ll go beyond theoretical and lean into what’s practical.&lt;/p&gt;

&lt;p&gt;We'll tackle what to understand, what to pay attention to, and what should be running in the back of your mind as you start working inside a &lt;em&gt;real&lt;/em&gt; company's AWS environment.&lt;/p&gt;

&lt;p&gt;&lt;a id="First"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your first surprise comes quickly
&lt;/h2&gt;

&lt;p&gt;One of the first thing you'll notice is that AWS at your job feels very different from the AWS environment you learned tutorials and built projects in.&lt;/p&gt;

&lt;p&gt;A mental shift that helps is realizing you didn’t get hired to “learn AWS” in the abstract. There’s no clean starting point. There's no empty account waiting for you to build the “right” architecture. Instead, you’re stepping into an already existing system that includes, accounts, environments, pipelines, permissions, processes, conventions. All of it built for reasons you don’t fully understand yet.&lt;/p&gt;

&lt;p&gt;AWS is vast. There are &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;more than 200 services&lt;/a&gt;, which is exciting but as a first time developer, can be annoying at the same time. The good news is that most teams don’t use them all. In day-to-day work, AWS usually shows up in a few main technical areas like compute, storage, networking, security, databases, analytics, artificial intelligence, machine learning, observability, and deployment tooling. If you learn how your team uses those areas, the rest starts to feel manageable.&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%2Fez0or6s3xstzx0stqaof.webp" 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%2Fez0or6s3xstzx0stqaof.webp" alt="Amazon CTO standing in front of background of over 200 AWS services" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s easy to feel behind here. A lot of new developers assume everyone else knows what’s going on and they’re the only one catching up. That assumption is almost always wrong! What matters early is not how much you know but how well you learn the shape of the system you just joined.&lt;/p&gt;

&lt;p&gt;&lt;a id="Categories"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS categories you need early
&lt;/h2&gt;

&lt;p&gt;It helps to mentally group AWS into the big categories developers actually work in. &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%2Fwytuxnasfpml1s9hw3it.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%2Fwytuxnasfpml1s9hw3it.png" alt="Tiled list of AWS services categories" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compute is where code runs. This could be AWS Lambda for serverless functions, &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon EC2&lt;/a&gt; for virtual machines, or containers on &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon ECS&lt;/a&gt; or &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon EKS&lt;/a&gt;. Storage is where files and artifacts live, usually in Amazon S3. Databases hold application state, commonly stored in &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon DynamoDB&lt;/a&gt; or &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon RDS&lt;/a&gt;. Networking is how services connect and communicate safely, which is where &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon VPC&lt;/a&gt;, subnets, security groups, and load balancers like an &lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Application Load Balancer&lt;/a&gt; show up. Security sits across everything through Amazon IAM, &lt;a href="https://docs.aws.amazon.com/kms/latest/developerguide/overview.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS KMS&lt;/a&gt;, and network boundaries. Observability is how you see what’s happening in your systems in production through services like Amazon CloudWatch and &lt;a href="https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS X-Ray&lt;/a&gt;, and audit trails like &lt;a href="https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CloudTrail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You absolutely do not have to master all of these in week one, you just want enough familiarity to recognize what you’re looking at so you can ask more effective questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  You're stepping into your company's AWS environment, not a lesson plan
&lt;/h2&gt;

&lt;p&gt;Know that you got hired to work inside a specific AWS environment that already supports real users and real business needs.&lt;/p&gt;

&lt;p&gt;Your immediate objective is to understand how things work well enough to change them without causing damage, how code gets deployed, how services talk to each other, how failures are noticed and handled and how access is controlled.&lt;/p&gt;

&lt;p&gt;A simple but powerful habit in your first week is getting clarity on where you are. Answer questions like, which AWS account are you in, which region are you in, are you in a development, staging, or production environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/about-aws/global-infrastructure/" rel="noopener noreferrer"&gt;AWS Regions and Availability Zones&lt;/a&gt; matter because they shape latency, resilience, and where resources physically live. If you hear someone say “this is in us-east-1” or “that workload is multi-AZ,” they’re not trying to test your alphanumeric understanding, they're just giving context to where and how resources are deployed.&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%2Fvyig5vbf9x8gzhjw7q76.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%2Fvyig5vbf9x8gzhjw7q76.png" alt="Architectural Diagram of AWS Regions, Availability Zones and Subnets" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I made my own transition into tech from a completely different career, this took time to sink in. Before the cloud, I was a professional athlete. Progress in that career, came from understanding the system you were competing in and improving inside it. AWS turned out to be similar. Once I stopped trying to know everything and started trying to understand the environment I was in, the learning curve flattened out.&lt;/p&gt;

&lt;p&gt;&lt;a id="Terminal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your terminal becomes important very fast
&lt;/h2&gt;

&lt;p&gt;Early on, you’ll probably write less code than you expected. That’s normal!&lt;/p&gt;

&lt;p&gt;Most of your first week is about setup. Getting your local environment working the way your team expects. Installing the &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CLI&lt;/a&gt;. Understanding how authentication works at your company. Maybe it’s &lt;a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS IAM Identify Center&lt;/a&gt; for Single Sign-On (SSO), maybe it’s using temporary credentials through &lt;a href="https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Security Token Service&lt;/a&gt; or maybe it’s multiple CLI profiles tied to different accounts.&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%2Fosxhjqgqelpf9eerxwa8.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%2Fosxhjqgqelpf9eerxwa8.png" alt="Local terminal running the AWS CLI command " width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However it’s done, you want to understand how requests from your laptop become actions in AWS. That clarity makes debugging easier and gives you confidence when something doesn’t work.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/what-is.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Console&lt;/a&gt; is useful, especially when you’re new but the terminal is where most developers spend their time once they’re comfortable. It’s faster, repeatable, and closer to how things actually run in automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissions are usually the problem
&lt;/h2&gt;

&lt;p&gt;At some point, something will fail in a way that doesn’t make sense. Your code looks right. The resources exist. You'll try it again and receive the same result.&lt;/p&gt;

&lt;p&gt;This is usually where permissions enter the picture. Permissions is one of the first debugging steps to check when you’re receiving errors while trying to read or change resources.&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%2F415iepg91ix8m2ucv6g5.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%2F415iepg91ix8m2ucv6g5.png" alt="Permission error when trying to make change to a resources in AWS Console" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Identity and access controls are at the center of AWS, and they trip everyone up early on. A lot of issues aren’t logic errors at all but they’re actually boundaries set that are doing exactly what they’re supposed to do. In real environments, you’ll run into IAM roles and policies, resource-based policies like Amazon S3 bucket policies, and sometimes encryption rules enforced through AWS KMS.&lt;/p&gt;

&lt;p&gt;Once you start thinking in terms of who is making a request, what they’re allowed to do, and which resource is involved, AWS permissions becomes easier to reason about. Treating IAM as a core skill early, and learning to recognize permission failures will quickly save you a lot of debugging frustration.&lt;/p&gt;

&lt;p&gt;&lt;a id="Existed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Most of what you touch already existed before you arrived
&lt;/h2&gt;

&lt;p&gt;At your new job, you will inherit infrastructure before you will design anything new.&lt;/p&gt;

&lt;p&gt;That infrastructure is usually defined as code using Infrastructure as Code (IaC) tools like &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CloudFormation&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/home.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CDK&lt;/a&gt; or &lt;a href="https://developer.hashicorp.com/terraform/docs" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt;. These tools allow infrastructure to be versioned, reviewed, and deployed like application code. Even if you’re not writing it yet, learning how to read it matters!&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%2Fqeken3za0334s7si592a.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%2Fqeken3za0334s7si592a.png" alt="Steps of utilizing AWS CloudFormation to deploy resources on AWS." width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll also start noticing where that infrastructure connects to delivery workflows. If your team uses &lt;a href="https://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CodePipeline&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CodeBuild&lt;/a&gt;, or even a mix like &lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt; plus CloudFormation, then these are the path your developer changes will follow.&lt;/p&gt;

&lt;p&gt;Being able to tell what will change before it changes is how teams avoid breaking production. Developers who take the time to understand existing infrastructure build trust quickly because they’re showing respect for the system.&lt;/p&gt;

&lt;p&gt;&lt;a id="Serverless"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless may force you to change how you think
&lt;/h2&gt;

&lt;p&gt;There’s a good chance your new role involves serverless, and that’s another adjustment.&lt;/p&gt;

&lt;p&gt;You will have to pause to stop thinking primarily about servers and start thinking about triggers and events. For example, an API request comes into Amazon API Gateway and invokes an AWS Lambda function, a file upload lands in Amazon S3 and triggers processing, a message arrives in &lt;a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-getting-started.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon SQS&lt;/a&gt; or &lt;a href="https://docs.aws.amazon.com/sns/latest/dg/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon SNS&lt;/a&gt; and kicks off work, an event is routed through &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon EventBridge&lt;/a&gt;, a workflow spans multiple steps using &lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Step Functions&lt;/a&gt; and an application’s state that lives in Amazon DynamoDB.&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%2Fq2v3hjcpq5om63ve5w9t.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%2Fq2v3hjcpq5om63ve5w9t.png" alt="Image of event-driven processes utilizing AWS serverless services" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This mindset will affects how you write code and how you handle failure. You'll start caring about retries, idempotency, and visibility earlier because distributed systems fail in messy ways. You'll also start thinking about scalability differently because serverless services scale automatically, but they still have limits and concurrency behaviors you need to understand.&lt;/p&gt;

&lt;p&gt;&lt;a id="Change"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn how changes reach production before making one
&lt;/h2&gt;

&lt;p&gt;Before you ship anything meaningful, it helps to understand how a change actually makes it to production.&lt;/p&gt;

&lt;p&gt;Figure out what starts the deployment process. Learn whether approvals are needed. Understand how environments are separated. Ask what happens when something fails and how rollbacks are handled.&lt;/p&gt;

&lt;p&gt;If your team uses AWS CodePipeline, GitHub Actions, &lt;a href="https://docs.gitlab.com/" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt; or a Git-based workflow, watch a few deployments go through before you touch anything major. This will be critical to understand because when things go wrong, the calmest developers are usually the ones who understand the delivery system.&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%2F3521hj19fzbz152glt4b.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%2F3521hj19fzbz152glt4b.png" alt="CI/CD process utilizing AWS CD/CD services to deploy changes to prod" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Knowing this upfront will keep you from guessing later, and make you calmer when you do ship your first change.&lt;/p&gt;

&lt;p&gt;&lt;a id="Observe"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Observe before you optimize
&lt;/h2&gt;

&lt;p&gt;Production systems don’t always announce problems clearly. Logs, metrics, and traces are how you will figure out what’s happening when you’re not watching. In serverless environments especially, they’re your only way to real visibility.&lt;/p&gt;

&lt;p&gt;You’ll likely spend time in Amazon CloudWatch Logs and Metrics, and in some environments you’ll also use AWS X-Ray for tracing. When someone asks “who changed this,” that’s where AWS CloudTrail becomes useful because it shows all API activity to help you understand what happened.&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%2Fon71xyibp75znc13u7mu.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%2Fon71xyibp75znc13u7mu.png" alt="CI/CD process utilizing AWS CD/CD services to deploy changes to prod" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spending time early just observing how systems behave helps you build intuition. Over time, you start to recognize what normal looks like, which makes it easier to spot when something isn’t.&lt;/p&gt;

&lt;p&gt;&lt;a id="Cost"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost will show up sooner than you expect
&lt;/h2&gt;

&lt;p&gt;It’s better to learn this early because contrary to the tutorials you’ve done, developing on AWS at your job is not purely technical. There’s an economic side to operating in the cloud that directly affects your company’s business.&lt;/p&gt;

&lt;p&gt;Every decision has a cost attached to it. You don’t need to be perfect about this early on, but you should be aware. Leaving things running, misconfiguring resources, or forgetting to cleanup adds up quickly. In most teams, you’ll use &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/ce-what-is.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Cost Explorer&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-managing-costs.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Budgets&lt;/a&gt;, and some will rely on the &lt;a href="https://docs.aws.amazon.com/cur/latest/userguide/what-is-cur.html?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Cost and Usage Report&lt;/a&gt; for deeper reporting. Tagging resources also matters more than people expect because it’s how teams attribute cost to systems and owners.&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%2F3gpm9k2ymr4na3jag5qc.jpg" 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%2F3gpm9k2ymr4na3jag5qc.jpg" alt="Cost Explorer cost and usage graph" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers who pay attention to cost tend to think more carefully about trade-offs, and that mindset shows maturity. It also signals that you understand you’re building for a business, not just for a demo.&lt;/p&gt;

&lt;p&gt;&lt;a id="Certifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Certifications can help if you want structure
&lt;/h2&gt;

&lt;p&gt;You don’t need a certification to be successful in your first AWS developer job. Plenty of great developers never pursue one. That said, certifications can be genuinely useful when you’re feeling overwhelmed and want a structured way to build familiarity with AWS and how things fit together.&lt;/p&gt;

&lt;p&gt;The real value is often in the process of studying, not the exam itself. Preparing for an &lt;a href="https://aws.amazon.com/certification/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS certification&lt;/a&gt; forces you to slow down and learn how AWS expects systems to be build and &lt;a href="https://aws.amazon.com/architecture/well-architected/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;architected well&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During this process, you'll start to see recurring patterns around compute, networking, security, storage, scalability, and fault tolerance. You'll also begin to understand why certain services are paired together and why some designs are preferred over others. That kind of exposure helps you develop better instincts long before you’re asked to design anything on your own on the job.&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%2Fkaa67thhsuc5s06gca99.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%2Fkaa67thhsuc5s06gca99.png" alt="AWS Certification Path guide for developers" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re early in your journey and want a broad foundation, the &lt;a href="https://aws.amazon.com/certification/certified-cloud-practitioner/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Certified Cloud Practitioner&lt;/a&gt; can help you build vocabulary and basic cloud context. It introduces you to core services, &lt;a href="https://aws.amazon.com/compliance/shared-responsibility-model/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;shared responsibility&lt;/a&gt;, pricing concepts, and the global nature of AWS without going too deep too fast.&lt;/p&gt;

&lt;p&gt;If you want to go a level deeper into what you’ll actually see in a developer role, the &lt;a href="https://aws.amazon.com/certification/certified-developer-associate/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Certified Developer Associate&lt;/a&gt; and the &lt;a href="https://aws.amazon.com/certification/certified-solutions-architect-associate/?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Certified Solutions Architect Associate&lt;/a&gt; certifications are a natural next steps.&lt;/p&gt;

&lt;p&gt;The AWS Solutions Architect Associate focuses on how systems are designed on AWS as a whole. You spend time thinking about cost efficiency, performance, reliability, and scalability. You learn how different services work together and how architectural decisions affect long-term outcomes. For many, this certification is where AWS stops feeling like a collection of isolated services and starts feeling more cohesive.&lt;/p&gt;

&lt;p&gt;Studying for the AWS Developer Associate exposes you to how applications are built and deployed on AWS. It includes topics like serverless development, CI/CD workflows, monitoring, and troubleshooting, which will help you understand how code behaves once it leaves your laptop and runs in AWS. &lt;/p&gt;

&lt;p&gt;These certifications are accelerators for learning and will help you stay oriented while you’re building experience, but know that they are not the destination. You can always look into pursuing many other AWS or industry certifications offered but remember, the magic only happens when you apply those concepts on the job, one change, one system and one debug session at a time.&lt;/p&gt;

&lt;p&gt;&lt;a id="Conclusion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Expectations and what really matters
&lt;/h2&gt;

&lt;p&gt;For your first AWS developer job, you're not expected to be an expert. Early success looks like learning how to operate inside a complex system, asking good questions, making safe changes, understanding impact, and improving steadily.&lt;/p&gt;

&lt;p&gt;That approach is what helped me move from a completely different career into cloud development, and it’s what I’ve seen work consistently for others. Your journey of a new developer on AWS will depend on how you take the time to understand the environment you’re working in.&lt;/p&gt;

&lt;p&gt;If you do that, you’ll ramp up faster than you think and set yourself up for everything that comes next.&lt;/p&gt;

&lt;p&gt;Lastly, if you're looking to dive deeper in your learning journey, explore these FREE AWS resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/free?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Free Tier Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://builder.aws.com/start?trk=e3f50ee1-3e9a-412b-b5ed-61c3791a9fba&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Builder Center Sign Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/XFPX3M7HAQ/introduction-to-aws-identity-and-access-management-iam/DQJ3N5QRRU?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to Identity and Access Management (IAM)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://skillbuilder.aws/learn/J59SS92GUN/aws-billing-and-cost-management/25JXE6WYAY?trk=ddc7640f-4b0f-4289-896a-4c93114ffd04&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Intro to AWS Billing Services and Cost Management
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Good luck!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;If you've got this far, thanks for reading! I hope it was worthwhile.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>developer</category>
      <category>cloud</category>
      <category>devrel</category>
    </item>
  </channel>
</rss>
