<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Benedicta on Medium]]></title>
        <description><![CDATA[Stories by Benedicta on Medium]]></description>
        <link>https://medium.com/@techwriterb?source=rss-57ad158335cd------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*kSfIBT_zUjKIoDFLdW3j9g.jpeg</url>
            <title>Stories by Benedicta on Medium</title>
            <link>https://medium.com/@techwriterb?source=rss-57ad158335cd------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 28 May 2026 03:06:19 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@techwriterb/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Building CloudSentinel AI During the MeDo Hackathon]]></title>
            <link>https://techwriterb.medium.com/building-cloudsentinel-ai-during-the-medo-hackathon-466a15fb3954?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/466a15fb3954</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[hackathons]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Sat, 16 May 2026 22:26:33 GMT</pubDate>
            <atom:updated>2026-05-16T22:37:20.057Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QjpyRw8smbStreldUNqUnA.png" /><figcaption>cloudsentinel dashboard</figcaption></figure><p>For MeDo Hackathon, i built <strong>CloudSentinel AI, </strong>an infrastructure incident investigation platform that analyzes cloud and system logs to help developers find failures faster.</p><p>I haven’t personally been paged at 3 AM for a production outage. The idea came from thinking about where developers lose the most time during debugging, and log analysis kept coming up. Logs rarely explain what broke, they show you what reacted to what broke. Finding the actual cause of a deployment failure means reading through thousands of lines and manually connecting events. That takes a long time, and it doesn’t have to.</p><h3>What It Does</h3><p>You paste in your logs from Kubernetes pod output, Docker container logs, CI/CD failures, API gateway logs, whatever and the platform runs an investigation. The output is organized into six sections.</p><ol><li><strong>Severity classification.</strong> The platform reads error density and signal patterns to triage the incident. Not every failure is a P0.</li><li><strong>Infrastructure signals.</strong> Which services and components were involved. Memory pressure, misconfigured readiness probes, cert expiry. This surfaces automatically from the logs.</li><li><strong>Correlated failure detection.</strong> A database connection pool maxing out triggers API failures, which trigger pod restarts, which trigger health check failures. The platform traces those connections instead of treating each error in isolation. This is the part i spent the most time on.</li><li><strong>Investigation timeline.</strong> A chronological reconstruction of how the incident unfolded, so you can see the cascade rather than a flat list of unrelated log lines.</li><li><strong>Root cause analysis.</strong> A structured assessment with a confidence score and a readable explanation of the reasoning. You can push back on it if it’s wrong.</li><li><strong>Recommended fixes.</strong> Next steps grounded in what the logs actually showed.</li></ol><p>The result is a structured hypothesis with evidence attached. You still make the call. But you start from somewhere instead of from nothing.</p><h3>How It Works</h3><p>The analysis runs on <strong>Gemini 2.5 Flash</strong>, called through a Supabase Edge Function on Deno. The hard part was the prompting.</p><p>Getting a model to return grounded analysis on messy infrastructure logs, without inventing explanations the data doesn’t support, took a lot of iteration. I structured the prompt to force layered reasoning: identify signals, find correlations, form a root cause hypothesis, then suggest fixes. Each stage feeds the next.</p><p>Production logs are also massive. One incident can produce tens of thousands of lines. I built a chunking layer that extracts the most signal-dense portions before sending anything to the model. Critical errors in, routine INFO noise out.</p><p>The UI took several passes. Investigation tools carry a lot of information, and the challenge is organizing it for someone who is already stressed about an outage. I landed on a card-based layout styled after the dark observability dashboards engineers use during incidents.</p><h3>What Went Wrong During the Build</h3><p>Getting the model to return consistent, valid JSON with nested arrays and confidence scores was harder than i expected. I had to build a fallback layer for malformed responses, and the prompt went through many revisions before the output was reliable.</p><p>The database schema also needed a mid-hackathon migration. The initial design couldn’t represent correlated failures or investigation timelines, so i added six columns and updated the edge functions, types, and four UI pages. Lesson: think harder about data shape before writing the first query.</p><p>Edge cases in real log formats are also messy. Truncated output from crashed containers, mixed log formats, unusual environments . Those still produce imperfect results sometimes.</p><h3>What I Took Away</h3><p>The most reliable AI features i’ve seen are attached to a specific workflow and solve one repetitive problem well. CloudSentinel works better than a general chatbot for this task because the output is structured for the workflow, not for conversation.</p><p>Prompting is also a design problem. The difference between a flaky AI feature and a dependable one usually comes down to how well you’ve constrained the model’s reasoning. It’s not about clever wording.</p><h3>What’s Next</h3><p>Live log streaming is the main thing missing. Right now the platform is batch-based. You submit logs and get a report. A streaming version could surface investigation drafts in real time as an incident develops.</p><p>After that: infrastructure topology mapping (so the platform understands how your services connect, not just what they log), team collaboration features for shared investigations, and eventually historical pattern matching so past incidents can inform new ones.</p><p>If you’ve spent two hours reading logs to find a 30-second fix, you know the problem. That’s what I built this for.</p><p>CloudSentinel AI is live <a href="https://app-bo9vd99k16o1.appmedo.com">here</a></p><p>#BuiltWithMeDo</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=466a15fb3954" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Full-Stack AWS Architecture for Frontend Developers]]></title>
            <link>https://techwriterb.medium.com/understanding-full-stack-aws-architecture-for-frontend-developers-6b8c6ee43be9?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/6b8c6ee43be9</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[serverless]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Wed, 04 Mar 2026 07:15:35 GMT</pubDate>
            <atom:updated>2026-05-08T06:57:05.295Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mW3OdQg6p8Aa7-BJP1VD5w.png" /></figure><p>If you’re comfortable building React applications but haven’t worked with AWS before, the implementation tutorial that follows this article will introduce several technologies at once: Lambda, API Gateway, DynamoDB, Cognito, and CDK. Without some grounding, each of those can feel like an unfamiliar piece in a puzzle you haven’t seen the box for.</p><p>This article is that box. It explains what each technology is, why it exists, and exactly where it appears in the Vendor Management App you’re about to build. No implementation yet . This is just the mental model.</p><h3>1. Why Full-Stack Architecture?</h3><p>When you build a React app that uses a managed backend like Firebase or Supabase, the infrastructure layer is hidden from you. Someone else designed the database, the API, the authentication, and the hosting. That’s fine for many projects. But when you move to AWS, you’re given the raw components and asked to wire them together yourself.</p><p>It’s the difference between using a framework and understanding what the framework is doing. Once you can define your own infrastructure, you understand what every layer of your application is actually responsible for and you can change, scale, or debug any part of it.</p><p>A full-stack application, at its most basic, has four distinct concerns:</p><p><strong>Frontend — </strong>what the user sees and interacts with. In our case, a React application built with Next.js. The frontend has no direct access to the database. It can only ask the backend for data.</p><p><strong>Backend</strong> — the logic layer that handles requests, enforces rules, and talks to the database. In our app, this is a set of Lambda functions. They receive a request, process it, and return a response.</p><p><strong>Infrastructure</strong> — the underlying AWS services that host and connect everything: the database, the API endpoint, the CDN, the storage bucket. These exist whether your app is running or not.</p><p><strong>Authentication</strong> — the system that verifies who a user is and whether they’re allowed to do what they’re trying to do. In our app, this is Amazon Cognito. It sits outside the request flow but influences every protected request that passes through it.</p><p>Separating these concerns is what makes the system maintainable. Your frontend doesn’t need to know how the database stores data. Your Lambda doesn’t need to know how the user logged in. Each layer has one responsibility, and they communicate through defined contracts.</p><h3>2. Understanding the Request Flow</h3><p>Before writing any code, you need a clear picture of what happens when a user clicks “Add Vendor” in the app. Here is the full flow:</p><pre>Browser → CloudFront → API Gateway → Lambda → DynamoDB</pre><p>Let’s walk through each step.</p><h3>Browser</h3><p>The user’s browser is running your compiled React application. When the user fills in a form and submits it, the browser constructs an HTTP request, a POST request with the vendor data as JSON in the body. That request needs somewhere to go. It goes to a URL, and that URL points to CloudFront.</p><p>The browser doesn’t know anything about Lambda or DynamoDB. It sends a standard HTTP request, the same as it would to any other API.</p><h3>CloudFront</h3><p>CloudFront is AWS’s Content Delivery Network (CDN). It has two jobs in this application.</p><p>First, it serves the static frontend. When you build your Next.js app and export it as static files, those files — HTML, CSS, JavaScript — are stored in an S3 bucket. CloudFront sits in front of that bucket and delivers those files to users through a network of edge locations distributed globally. A user in Tokyo gets the files from a server near Tokyo, not from a data center in Virginia.</p><p>Second, CloudFront provides the HTTPS URL that your frontend uses to talk to the backend. Rather than exposing your API Gateway URL directly to the public, you route API requests through CloudFront. This gives you a single domain for both static content and API traffic.</p><p>Think of CloudFront as the front desk. It receives every incoming request, delivers static content directly, and forwards API requests inward to the appropriate destination.</p><p><strong>In the Vendor Management App:</strong> CloudFront hosts the React frontend and forwards API requests to API Gateway.</p><h3>API Gateway</h3><p>API Gateway is the entry point to your backend logic. It’s a managed AWS service that receives HTTP requests and routes them to the appropriate handler — in our case, a Lambda function.</p><p>You define routes on API Gateway: POST /vendors goes to the create Lambda, GET /vendors goes to the read Lambda, DELETE /vendors goes to the delete Lambda. API Gateway handles the routing, the protocol, and critically, authentication. Before it sends a request to Lambda, it can check whether the request carries a valid identity token. If it doesn&#39;t, the request is rejected at this layer. Lambda never sees it.</p><p>Think of API Gateway as a reception desk with a security checkpoint. It checks your ID (the Cognito token), then directs you to the right room (the Lambda function).</p><p><strong>In the Vendor Management App:</strong> API Gateway exposes the /vendors endpoint, validates JWT tokens using Cognito, and routes each HTTP method to the correct Lambda function.</p><h3>Lambda</h3><p>Lambda is where your application logic lives. A Lambda function is a piece of code that runs in response to an event, in this case, an HTTP request from API Gateway. It runs, does its job, and stops. There is no server running continuously, waiting for requests.</p><p>When a user POSTs a new vendor, API Gateway triggers the createVendor Lambda. That function receives the request, extracts the vendor data from the body, generates an ID, and writes the record to DynamoDB. It then returns a response, a status code and a message, back through API Gateway to the browser.</p><p>Lambda functions are isolated. Each function does one thing. createVendor creates. getVendors retrieves. They share the same database but operate independently.</p><p><strong>In the Vendor Management App:</strong> Two Lambda functions handle the vendor data, one writes to DynamoDB, one reads from it. A third handles deletion.</p><h3>DynamoDB</h3><p>DynamoDB is AWS’s NoSQL database service. Every vendor record the user creates is stored here. Lambda reads from and writes to this table. The frontend never touches DynamoDB directly , it goes through Lambda every time.</p><p>DynamoDB is a managed service. You don’t provision a database server. You define a table, set the key structure, and AWS handles storage, replication, and availability.</p><p><strong>In the Vendor Management App:</strong> A single DynamoDB table named VendorTable stores all vendor records. Lambda accesses it using the AWS SDK.</p><h3>3. What is AWS CDK and Why Use It?</h3><h3>Infrastructure as Code</h3><p>Traditional AWS usage involves logging into the AWS Console and clicking through forms to create resources: Create table, Create function, Create API. This works, but it has real problems. It’s not repeatable, if you need to recreate the infrastructure in a new environment, you click through every form again. It’s not auditable, there’s no record of what was created or why and it’s error-prone.</p><p>Infrastructure as Code (IaC) solves this by letting you define your infrastructure in a file, the same way you define a React component. The file is the source of truth. You commit it to version control. You deploy from it. You can tear everything down and rebuild it identically with a single command.</p><h3>What CDK Is</h3><p>AWS CDK (Cloud Development Kit) is a framework for writing Infrastructure as Code using real programming languages — TypeScript, Python, Java, and others. In our tutorial, we use TypeScript.</p><p>CDK lets you write something like this:</p><pre>const vendorTable = new Table(this, &#39;VendorTable&#39;, {<br>  partitionKey: { name: &#39;vendorId&#39;, type: AttributeType.STRING },<br>});</pre><p>That TypeScript code describes a DynamoDB table. It’s not creating the table yet but describing what the table should look like.</p><h3>How CDK Works Under the Hood</h3><p>When you run cdk deploy, CDK takes your TypeScript definitions and <strong>synthesizes</strong> them into a CloudFormation template, a JSON or YAML file that describes every AWS resource in precise detail. AWS CloudFormation then reads that template and creates or updates the actual resources in your account.</p><p>As a developer, you don’t write the CloudFormation template directly. CDK generates it for you from your TypeScript code.</p><pre>Your TypeScript (CDK) → CloudFormation Template → Real AWS Resources</pre><h3>Why is this important for the tutorial?</h3><p>In the implementation guide, you’ll write your entire backend, the database, the Lambda functions, the API, the authentication, in a single TypeScript file called backend-stack.ts. When you run cdk deploy, all of it appears in AWS. When you run cdk destroy, all of it is removed. No manual cleanup or orphaned resources.</p><p><strong>In the Vendor Management App:</strong> CDK defines the DynamoDB table, both Lambda functions, the API Gateway, the Cognito User Pool, the S3 bucket, and the CloudFront distribution. One file, one deployment command.</p><h3>4. Serverless Explained</h3><h3>What “Serverless” Actually Means</h3><p>Serverless doesn’t mean there are no servers. It means you don’t manage them. AWS runs your code on its own infrastructure, scales it automatically, and bills you only for the time your code is actually executing.</p><p>In a traditional backend, you’d provision a server, an EC2 instance, a container, a VPS, and it runs 24 hours a day regardless of whether anyone is using your app. You pay for uptime. You’re responsible for patching, scaling, and monitoring the machine.</p><p>With Lambda, you deploy a function. AWS runs it when it’s triggered, for as long as it takes to complete, and then stops. A Lambda function handling ten requests per day costs almost nothing. A Lambda function handling ten million requests scales automatically without any configuration change on your part.</p><h3>Event-Driven Execution</h3><p>Lambda functions don’t run continuously. They wait for events. An event can be many things: an HTTP request from API Gateway, a file upload to S3, a message in a queue, a scheduled timer. In our app, the event is always an HTTP request arriving at API Gateway.</p><p>When API Gateway receives a POST /vendors request, it packages the request data into a structured event object and passes it to the createVendor Lambda. The function receives that object as its event parameter, processes it, and returns a response. The entire execution might take 50 milliseconds.</p><pre>export const handler = async (event: any) =&gt; {<br>  const body = JSON.parse(event.body);<br>  // ... process the request<br>  return { statusCode: 201, body: JSON.stringify({ message: &quot;Vendor Created&quot; }) };<br>};</pre><h3>Why This Architecture Scales</h3><p>Because each Lambda invocation is independent, the system handles concurrent requests naturally. If 500 users submit a vendor form at the same time, AWS runs 500 instances of your Lambda function in parallel. You didn’t configure that nor provision extra capacity. It just works.</p><p>For a learning project, this also means you have no idle infrastructure costs. The database exists and incurs a small storage cost, but the Lambda functions only cost money when someone uses them.</p><p><strong>In the Vendor Management App:</strong> Each Lambda function is a focused, stateless handler. It receives a request, interacts with DynamoDB, and returns a response. It has no memory of previous requests.</p><h3>5. API Gateway and REST APIs</h3><h3>How Frontend and Backend Communicate</h3><p>A REST API is a convention for structuring communication between a frontend and a backend over HTTP. It uses HTTP methods — GET, POST, PUT, DELETE — to indicate what the client wants to do, and URL paths to indicate what resource it wants to do it to.</p><pre>GET    /vendors        → Retrieve all vendors<br>POST   /vendors        → Create a new vendor<br>DELETE /vendors        → Delete a vendor by ID</pre><p>In our app, API Gateway implements this REST API. You define the routes in CDK, and API Gateway handles receiving the HTTP requests and dispatching them to the right Lambda function.</p><p>Your frontend doesn’t call Lambda directly. It can’t. Lambda functions don’t have public URLs by default. API Gateway is what provides the public-facing URL and the routing logic.</p><h3>Authentication Integration</h3><p>API Gateway has a built-in concept called an <strong>Authorizer</strong>. An Authorizer is a component that runs before your Lambda handler and decides whether to allow the request through.</p><p>In our app, we use a <strong>Cognito User Pool Authorizer</strong>. When a request arrives at API Gateway, the Authorizer extracts the token from the Authorization header and sends it to Cognito for validation. Cognito checks whether the token is genuine and unexpired. If it is, the request proceeds to Lambda. If it isn&#39;t, API Gateway returns a 401 Unauthorized response immediately.</p><p>This means your Lambda functions never have to handle authentication themselves. That concern is fully handled at the API Gateway layer, before your code runs.</p><p><strong>In the Vendor Management App:</strong> The POST /vendors and DELETE /vendors routes have a Cognito Authorizer attached. The Lambda functions behind them can assume that any request they receive comes from a verified, logged-in user.</p><h3>6. DynamoDB Fundamentals</h3><h3>NoSQL Basics</h3><p>DynamoDB is a NoSQL database, which means it doesn’t store data in tables with fixed schemas the way a relational database like PostgreSQL does. Instead, it stores items, you can think of them as JSON objects, in a table. Each item can have different fields. The only requirement is that every item has a <strong>partition key</strong>: a unique identifier.</p><p>This flexibility is well-suited to applications where the data structure evolves or where you don’t need complex relational queries across multiple tables. A vendor record in our app is a straightforward object: an ID, a name, a category, and an email. DynamoDB stores it cleanly without requiring you to define a rigid schema upfront.</p><h3>Partition Keys</h3><p>The partition key is what makes each item in a DynamoDB table unique. When you write an item, you must provide a value for the partition key. When you read an item directly, you look it up by that key.</p><p>In our app, the partition key is vendorId. Each new vendor gets a unique ID, in our Lambda, we generate one using Date.now().toString(). That ID becomes the partition key for that vendor&#39;s record.</p><pre>const vendorTable = new Table(this, &#39;VendorTable&#39;, {<br>  partitionKey: { name: &#39;vendorId&#39;, type: AttributeType.STRING },<br>});</pre><p>This CDK code tells AWS: “Create a DynamoDB table where every item is uniquely identified by a string field called vendorId.&quot;</p><h3>Why DynamoDB Fits This App</h3><p>DynamoDB is a natural fit here for three reasons. First, it’s a managed service, you define a table and AWS handles everything else. Second, it pairs cleanly with Lambda: both are serverless, both scale automatically, and the AWS SDK makes calling DynamoDB from a Lambda function straightforward. Third, for a list of vendor records with no complex relational requirements, a simple key-value store is the right tool. You don’t need joins, foreign keys, or transactions.</p><p><strong>In the Vendor Management App:</strong> A single VendorTable stores all vendor records. Lambda writes to it using PutCommand and reads from it using ScanCommand.</p><h3>7. Authentication with Cognito</h3><h3>What the Problem Is</h3><p>Without authentication, your API is open to anyone who discovers the URL. Anyone can create, read, or delete vendors with no identity required. For a real application, this is unacceptable.</p><p>Authentication answers two questions: <strong>Who are you?</strong> (identity) and <strong>Are you allowed to do this?</strong> (authorization). Cognito handles the identity part. API Gateway’s Authorizer handles the authorization check on each request.</p><h3>User Pools</h3><p>A Cognito <strong>User Pool</strong> is a managed directory of users. When someone signs up for your app, their email and password are stored in the User Pool. Cognito handles password hashing, account verification, password reset flows, and token issuance. You don’t build any of that.</p><p>In CDK, you define the User Pool with a few configuration options:</p><pre>const userPool = new cognito.UserPool(this, &#39;VendorUserPool&#39;, {<br>  selfSignUpEnabled: true,<br>  signInAliases: { email: true },<br>  autoVerify: { email: true },<br>});</pre><p>This tells AWS: create a User Pool where users can sign themselves up, use their email as their login, and have their email automatically verified during development.</p><h3>JWT Tokens</h3><p>When a user logs in successfully, Cognito issues a <strong>JWT</strong> (JSON Web Token). A JWT is a compact, cryptographically signed string that encodes information about the user with their ID, email, when the token was issued, and when it expires.</p><p>The token is signed by Cognito using a private key. This means that any service with access to Cognito’s public key, including API Gateway, can verify that the token is genuine without making a network call back to Cognito on every request.</p><p>The token looks like three base64-encoded strings joined by dots:</p><pre>eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyLWlkIn0.signature</pre><p>The frontend stores this token after login and attaches it to every API request in the Authorization header.</p><h3>How API Gateway Validates Tokens</h3><p>When a request arrives at a protected route, the Cognito Authorizer extracts the token from the Authorization header and validates its signature and expiry against the User Pool. This check happens entirely within AWS, before your Lambda function is invoked.</p><p>If the token is valid: the request proceeds to Lambda. If the token is missing, malformed, or expired: API Gateway returns 401 Unauthorized. Lambda is never called.</p><p><strong>In the Vendor Management App:</strong> The frontend uses the AWS Amplify library to manage the login flow and token storage. After login, fetchAuthSession() retrieves the current token, which is then attached to every protected API request.</p><h3>8. How All These Pieces Fit Together</h3><p>Here is the full architecture, reconstructed as a single coherent flow.</p><pre>┌─────────────────────────────────────────────────────────────────────────┐<br>│  AUTH LAYER                                                             │<br>│                    [ Cognito User Pool ]                                │<br>│                            |                                            │<br>│                     JWT Validation                                      │<br>│                            ↓                                            │<br>├─────────────────────────────────────────────────────────────────────────┤<br>│  FRONTEND / DELIVERY LAYER                                              │<br>│  [ Browser ] → [ CloudFront ] → [ API Gateway ]                        │<br>├─────────────────────────────────────────────────────────────────────────┤<br>│  BACKEND LAYER                                                          │<br>│  [ Lambda: createVendor ]  ──→  [ DynamoDB: VendorTable ]              │<br>│  [ Lambda: getVendors    ]  ←─  [ DynamoDB: VendorTable ]              │<br>└─────────────────────────────────────────────────────────────────────────┘</pre><p>Walk through it from the perspective of a user clicking “Add Vendor”:</p><ol><li>The user fills in the form and clicks submit. The React app calls fetchAuthSession() from Amplify and attaches the JWT token to the request header.</li><li>The browser sends a POST /vendors request with the vendor data in the body and the JWT in the Authorization header.</li><li>CloudFront receives the request and forwards it inward to API Gateway.</li><li>API Gateway’s Cognito Authorizer intercepts the request, extracts the JWT, and validates it against the User Pool. The token is valid. The request is allowed through.</li><li>API Gateway routes the POST /vendors request to the createVendor Lambda function.</li><li>The Lambda function executes. It parses the request body, generates a vendorId, and calls DynamoDB&#39;s PutCommand to write the new vendor record.</li><li>DynamoDB confirms the write. The Lambda function returns { statusCode: 201, body: &#39;{&quot;message&quot;: &quot;Vendor Created&quot;}&#39; }.</li><li>API Gateway receives the Lambda’s response and forwards it back to CloudFront.</li><li>CloudFront delivers the response to the browser.</li><li>The React app receives the 201 response, calls getVendors() to refresh the list, and re-renders the vendor cards with the new entry.</li></ol><p>The entire round trip, from click to updated UI, typically completes in under a second.</p><h3>What CDK’s Role Was in All of This</h3><p>Every component in that flow, the Cognito User Pool, the API Gateway, the Lambda functions, the DynamoDB table, the S3 bucket, the CloudFront distribution, was defined in a single TypeScript file and created in your AWS account with one command: cdk deploy.</p><p>CDK is not part of the runtime flow. It’s the tool that built the infrastructure before any user request was ever made. Once deployed, CDK’s job is done. The infrastructure runs independently.</p><h3>9. Moving to the Implementation Guide</h3><p>You now have a working mental model of every layer in the stack. You know what CloudFront does and why it’s in front of API Gateway. You know why Lambda functions are stateless and why that matters. You know what a JWT is and where it’s checked. You know that CDK is the tool that builds all of it from TypeScript.</p><p>When you follow the implementation tutorial and write this line:</p><pre>const vendorTable = new Table(this, &#39;VendorTable&#39;, {<br>  partitionKey: { name: &#39;vendorId&#39;, type: AttributeType.STRING },<br>  billingMode: BillingMode.PAY_PER_REQUEST,<br>});</pre><p>You’ll know exactly what that creates, why the partition key is structured that way, and where it sits in the broader architecture.</p><p>When you see event.body inside a Lambda function, you&#39;ll know that event is the structured object API Gateway built from the original HTTP request. When you see fetchAuthSession() in the frontend API service, you&#39;ll know that it&#39;s retrieving the Cognito JWT that API Gateway will check on the other end.</p><p>The implementation guide that follows builds the complete Vendor Management App from scratch: AWS account setup, CDK infrastructure, Lambda functions, Next.js frontend, Cognito authentication, and CloudFront hosting.</p><p><strong>Continue to the implementation guide: </strong><a href="https://www.freecodecamp.org/news/full-stack-aws-react-lambda-dynamodb-tutorial">Build a Full-Stack Vendor Management App Using React, AWS, and CDK</a></p><p><em>The concepts in this article apply beyond the Vendor Management App. The pattern, CDK-defined infrastructure, Lambda handlers, API Gateway routing, Cognito authentication, is a reusable foundation for any serverless application you build on AWS.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6b8c6ee43be9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Fix the "Unable to Resolve AWS Account" Error in AWS CDK]]></title>
            <link>https://techwriterb.medium.com/how-to-fix-the-unable-to-resolve-aws-account-error-in-aws-cdk-331c8d60edee?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/331c8d60edee</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[aws-cdk]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Tue, 24 Feb 2026 09:40:25 GMT</pubDate>
            <atom:updated>2026-02-24T09:40:25.753Z</atom:updated>
            <content:encoded><![CDATA[<h3>How I Fixed “Unable to Resolve AWS Account to Use” in AWS CDK</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Fli04omMty-vP6MDa_rrDw.png" /></figure><p>I was building a small backend with <strong>AWS CDK</strong>. A DynamoDB table, a Lambda function, and an API Gateway endpoint. Everything compiled until i tried to deploy and got this error:</p><blockquote>Unable to resolve AWS account to use. It must be either configured when you define your CDK Stack, or through the environment.</blockquote><p>Here is exactly what caused it and what fixed it.</p><h3>The Setup</h3><p>My stack looked like this:</p><ul><li>DynamoDB table for vendors</li><li>Lambda function to create a vendor</li><li>API Gateway REST API</li></ul><p>The Lambda environment originally looked like this:</p><pre>environment: {<br>  TABLE_NAME: vendorTable.tableName,<br>  account: process.env.CDK_DEFAULT_ACCOUNT_ID || cdk.Aws.ACCOUNT_ID,<br>  region: process.env.CDK_DEFAULT_REGION || cdk.Aws.REGION,<br>},</pre><p>My bin/backend.ts file had:</p><pre>import * as cdk from &#39;aws-cdk-lib/core&#39;;</pre><p>And I was using CDK v2.</p><h3>Why this error happens</h3><p>AWS CDK needs three things to deploy:</p><ol><li>An authenticated AWS identity</li><li>A resolved account and region</li><li>A bootstrapped environment</li></ol><p>If any of those are missing, stale, or misconfigured, CDK cannot determine where to deploy your stack. The frustrating part is that the error message makes it sound like your stack definition is wrong. In most beginner cases, it is not.</p><h3>Step 1: Verify and configure your AWS CLI</h3><p>Before touching your code, you must ensure your local machine actually knows who you are in the AWS ecosystem.</p><pre>aws sts get-caller-identity</pre><p>If it’s working, you’ll see your Account ID and IAM ARN. If it fails or returns nothing, your credentials are stale or missing.</p><h3>How to configure (or reconfigure) AWS</h3><p>If the command above failed, run the configuration wizard:</p><pre>aws configure</pre><p>You will be prompted for four pieces of information:</p><ul><li><strong>AWS Access Key ID:</strong> Your IAM user identifier.</li><li><strong>AWS Secret Access Key:</strong> Your IAM secret.</li><li><strong>Default region name:</strong> e.g., us-east-1 or eu-west-1.</li><li><strong>Default output format:</strong> (Press Enter for json).</li></ul><blockquote><strong><em>Pro Tip:</em></strong><em> If you use multiple AWS accounts, ensure your </em><em>AWS_PROFILE environment variable is set correctly before running CDK commands.</em></blockquote><h3>Step 2: Fix the CDK v2 imports</h3><p>If you are using <strong>CDK v2</strong>, using v1-style imports can cause internal conflicts in how the library resolves the environment.</p><p><strong>The Mistake:</strong></p><pre>import * as cdk from &#39;aws-cdk-lib/core&#39;; // This is CDK v1 style!</pre><p><strong>The Fix:</strong></p><p>In CDK v2, everything is bundled into the main library. Update your bin/backend.ts and stack files to:</p><pre>import * as cdk from &#39;aws-cdk-lib&#39;;</pre><h3>Step 3: Stop manual account injection</h3><p>I noticed iwas trying to help the Lambda function by manually passing account and region IDs into the environment variables. This was unnecessary and actually introduced more surface area for errors.</p><p><strong>What I removed:</strong></p><pre>// Delete these lines from your Lambda props<br>environment: {<br>  TABLE_NAME: vendorTable.tableName,<br>  account: process.env.CDK_DEFAULT_ACCOUNT_ID || cdk.Aws.ACCOUNT_ID, // Unnecessary<br>  region: process.env.CDK_DEFAULT_REGION || cdk.Aws.REGION,         // Unnecessary<br>},</pre><p><strong>Why?</strong> Lambda functions automatically have access to process.env.AWS_REGION and process.env.AWS_ACCOUNT_ID at runtime. Hardcoding or injecting them via CDK creates a circular dependency logic that can confuse the synthesizer.</p><h3>Step 4: Clear stale artifacts</h3><p>This is what finally solved it for me. CDK synthesizes your TypeScript code into CloudFormation templates inside a folder called cdk.out. If you changed your AWS configuration or updated your code, the old templates in cdk.out might be conflicting with your new settings.</p><p>Run this sequence to start fresh:</p><pre># 1. Delete the cached metadata<br>rm -rf cdk.out<br># 2. Recompile your TypeScript<br>npm run build<br># 3. Generate a fresh CloudFormation template<br>cdk synth<br># 4. Deploy<br>cdk deploy</pre><h3>Summary Checklist</h3><p>If you’re still stuck, run through this list in order:</p><ol><li><strong>ActionCommand / CheckCheck Identity</strong>aws sts get-caller-identity</li><li><strong>Reset Credentials</strong>aws configure</li><li><strong>Bootstrap</strong>cdk bootstrap (Required for new accounts/regions)</li><li><strong>Check Imports </strong>Ensure you use aws-cdk-lib, not /core</li><li><strong>Purge Cache</strong>rm -rf cdk.out &amp;&amp; cdk deploy</li></ol><p>One of these will fix it.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=331c8d60edee" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Think KodeKloud Powers Its AWS Labs with IAM Automation and STS]]></title>
            <link>https://techwriterb.medium.com/how-i-think-kodekloud-powers-its-aws-labs-with-iam-automation-and-sts-1206fa44aec8?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/1206fa44aec8</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[platform-engineering]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[cloud-architecture]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Wed, 18 Feb 2026 17:29:21 GMT</pubDate>
            <atom:updated>2026-02-18T17:29:21.668Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z6m80Zv52dE8rY5ETD22rg.png" /><figcaption>Hypothesized Hybrid IAM and STS Architecture for KodeKloud AWS Labs</figcaption></figure><p>I have been learning AWS IAM recently and I practice mostly using <a href="https://engineer.kodekloud.com/practice">KodeKloud</a> labs.</p><p>Every lab gives me a real AWS Console. I can launch EC2 instances, create S3 buckets, configure networking, attach policies. It feels like a real AWS account.</p><p>There are limits. I cannot access everything. I cannot escalate privileges, interfere with another student and after one hour, the entire environment disappears.</p><p>When I click “Start Lab”, I am automatically given:</p><ul><li>An AWS Console login URL</li><li>A username</li><li>A password</li><li>A working CLI environment</li></ul><p>So I started thinking. If I were running a platform like KodeKloud, how would I architect this?</p><p>Based on what I have learned so far, here is my technical hypothesis of how this likely works using a hybrid IAM and STS architecture.</p><p>This is not insider information. This is how I think it works as someone learning cloud and trying to reason through the design.</p><h3>First, What Are IAM and STS?</h3><p>Before I explain the architecture, let me clarify two important services.</p><h3>IAM</h3><p>AWS Identity and Access Management (IAM), is how AWS controls who can do what.</p><p>It allows you to create users, create groups, attach policies, define permissions and enforce least privilege.</p><p>IAM answers the question: Who is allowed to access which AWS resources and how?</p><p>If I create an IAM user and attach a restrictive policy, that user can only perform the actions explicitly allowed. That is the foundation of access control.</p><h3>STS</h3><p>AWS Security Token Service (STS), is about temporary credentials. Instead of giving someone permanent credentials, STS allows you to issue <em>temporary access keys</em>, <em>temporary session tokens</em> and <em>time bound permissions.</em></p><p>These credentials automatically expire.</p><p>It answers a different question: How do I give short lived, controlled access without permanent risk?</p><p>This critical for lab environments.</p><p>Now let us apply these ideas to KodeKloud.</p><p>KodeKloud has to:</p><ul><li>Give thousands of students real AWS access</li><li>Prevent cross access between students</li><li>Enforce least privilege</li><li>Prevent privilege escalation</li><li>Automatically expire sessions</li><li>Control cost</li><li>Clean up reliably</li></ul><p>This is a multi tenant IAM design problem layered with temporary credential control. IAM and STS together, solve the problem.</p><h3>1. The Foundation: A Controlled AWS Account</h3><p>At the core, they likely operate from one or multiple controlled AWS accounts. Inside those accounts, they probably maintain:</p><ul><li>Predefined VPC configurations</li><li>Base EC2 AMIs</li><li>S3 templates</li><li>IAM policy templates</li></ul><p>I do not think they create a brand new AWS account per student. That would be operationally heavy and expensive. Instead, they likely isolate students logically inside shared lab accounts.</p><h3>2. When You Click “Start Lab”</h3><p>When I click Start Lab, I believe backend automation does something like this:</p><ul><li>Generate a unique session ID</li><li>Provision required AWS resources</li><li>Create a new IAM user</li><li>Attach a restrictive policy or add the user to a predefined group</li><li>Generate a login profile with a password</li><li>Possibly generate temporary credentials via STS</li><li>Display credentials to me</li></ul><p>Example: kk-user-947201</p><p>This IAM user probably does not exist before I start the lab. It is created dynamically. This is automated IAM lifecycle management.</p><h3>3. IAM Groups and Policy Reuse</h3><p>To scale this system, they likely predefine IAM groups per lab type:</p><ul><li>VPC Lab Group</li><li>EC2 Lab Group</li><li>S3 Lab Group</li></ul><p>Each group has tightly scoped permissions.</p><p>When a session starts:</p><ul><li>A new IAM user is created</li><li>That user is added to the appropriate group</li></ul><p>This avoids recreating policies every time.</p><p>Alternatively, they could dynamically attach a session specific policy directly to the user. Either design works. The key principle is least privilege.</p><h3>4. Where STS Comes In</h3><p>Now it gets interesting. Even though I receive a username and password, I strongly suspect STS is involved behind the scenes.</p><p>There are two likely possibilities:</p><ol><li>The IAM user exists only as a base identity and assumes a restricted role via STS to operate.</li><li>The platform issues temporary credentials through STS that power the CLI environment and possibly the console session.</li></ol><p>Why would they do this? Because STS credentials:</p><ul><li>Automatically expire</li><li>Reduce long term credential risk</li><li>Enforce strict session boundaries</li></ul><p>So the architecture is likely hybrid. IAM defines identity and permission boundaries and STS enforces temporary access and expiration.</p><h3>5. Resource Isolation Using Tags</h3><p>Now the most important question: How does one student avoid touching another student’s resources?</p><p>My hypothesis is tagging plus IAM condition policies. When resources are created, they are tagged with something like: <em>Session-ID = 947201</em></p><p>Then IAM policies contain conditions such as: Allow access only if the resource tag Session-ID equals the user’s session ID. This means even inside the same AWS account:</p><ul><li>You only see your EC2 instances</li><li>You only modify your S3 buckets</li><li>You only manage your VPC</li></ul><h3>6. Why the CLI Works Too</h3><p>The lab also provides a CLI environment. That means one of two things is happening:</p><p><strong>Option A</strong><br>The IAM user has temporary programmatic credentials generated for that session.</p><p><strong>Option B</strong><br>The CLI environment assumes a restricted role via STS internally.</p><p>Either way, the same permission boundary applies. Whether I use the visual AWS Console or the CLI, the same IAM policies control what I can do.</p><h3>7. Session Expiration and Cleanup</h3><p>After one hour, automation likely triggers:</p><ul><li>Deletion of the IAM user</li><li>Removal of login profile</li><li>Deletion of access keys</li><li>Revocation of STS sessions</li><li>Termination of EC2 instances</li><li>Deletion of S3 buckets</li><li>Cleanup of networking resources</li></ul><p>The IAM user lifecycle becomes: <strong>Create &gt; Use &gt; Destroy</strong></p><p>Learning cloud has changed how I see platforms.</p><p>What feels like a simple one hour AWS lab is clearly backed by serious engineering. The console login, the working CLI, the strict limits, and the automatic teardown all point to a tightly controlled identity system operating behind the scenes.</p><p>My hypothesis is that each session dynamically creates an IAM user, and temporary credentials issued through STS enforce time bound, least privilege access inside a shared AWS account. IAM defines what I am allowed to do. STS ensures that access expires. Together, they make the lab safe and scalable.</p><p>I am still learning, so this is not an insider explanation. It is just me training myself to see the systems behind the surface.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1206fa44aec8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why your EC2 IP keeps changing]]></title>
            <link>https://techwriterb.medium.com/why-your-ec2-ip-keeps-changing-a9fe73a03063?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/a9fe73a03063</guid>
            <category><![CDATA[aws-ec2]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[ip-address]]></category>
            <category><![CDATA[elastic-ip]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Sat, 07 Feb 2026 16:31:53 GMT</pubDate>
            <atom:updated>2026-02-07T16:31:53.915Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bRlEqkBLxib5lcWM9KSEkQ.png" /></figure><h3><strong>Public IPs on EC2</strong></h3><p>When you launch an EC2 instance, AWS can give it a public IP address. That public IP is what allows the instance to be reached from the internet. Without it, the instance can still exist and run, but it won’t be directly accessible from outside AWS unless you put other networking components in front of it.</p><p>Instance needs to be reachable, so it gets a public IP butthis public IP is not permanent.</p><p>By default, the public IP assigned to an EC2 instance is tied to the instance’s lifecycle. If the instance is stopped and then started again, AWS releases that IP back into its pool and assigns a new one. From AWS’s point of view, this makes sense. Public IPv4 addresses are limited, and AWS treats them as temporary resources unless you explicitly ask for stability.</p><p>This behavior is fine for many use cases. If you’re testing, experimenting, or running short-lived workloads, the fact that the IP might change is not a problem. You can always look up the new address in the console. But the moment you imagine something external depending on that address, the problem becomes obvious.</p><p>If an application is hosted on that instance and users, services, or DNS records point to its public IP, a change breaks access. Nothing about the application itself changed. The server is still there. But the address people use to reach it is no longer valid.</p><h3>Elastic IPs and Stable Access</h3><p>An Elastic IP is a public IPv4 address that you explicitly allocate from AWS and keep under your control. Unlike the default public IP, it is not automatically tied to the lifecycle of an instance. You can associate it with an instance, disassociate it, and reattach it elsewhere. As long as you keep the Elastic IP allocated to your account, the address remains the same.</p><p>When you associate an Elastic IP with an EC2 instance, all incoming traffic to that IP is routed to the instance. If the instance is stopped and started, the Elastic IP does not change. If the instance fails and you launch a replacement, you can move the Elastic IP to the new instance and restore connectivity without changing anything outside AWS.</p><p>This is an important distinction. The Elastic IP is not a property of the instance. It is a separate networking resource that you attach to the instance. Thinking about it this way helped me understand why AWS treats Elastic IPs differently. You are essentially reserving a scarce public address and telling AWS that this address must remain stable, even if the compute behind it changes.</p><p>There are also cost implications. AWS charges for Elastic IPs that are allocated but not actively associated with a running instance. That pricing decision reinforces the idea that Elastic IPs are meant for intentional, long-lived access points, not something you casually allocate and forget.</p><p>From a practical standpoint, associating an Elastic IP is straightforward. You allocate the Elastic IP in the EC2 console, then associate it with an instance or a network interface. Once associated, the instance effectively stops using its auto-assigned public IP and uses the Elastic IP instead. Traffic coming in through that address reaches the instance, and outgoing traffic appears to originate from that same IP.</p><p>The <strong>server</strong> can be replaced. It can be stopped, started, resized, or rebuilt. The <strong>address</strong> is what the outside world knows. Elastic IPs allow you to keep that external reference stable while everything behind it remains flexible.</p><p>In real setups, Elastic IPs are often paired with DNS records, load balancers, or migration scenarios where you need continuity. They are also useful when you need to allowlist a fixed IP with a third-party service. Without a stable IP, you would constantly need to update external systems every time the instance restarts.</p><p>So the difference is not just that one IP changes and the other doesn’t. It’s about control and intent. A default public IP exists as a convenience. An Elastic IP exists because you deliberately asked for a permanent point of access.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a9fe73a03063" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Read-Only IAM Policies]]></title>
            <link>https://techwriterb.medium.com/understanding-read-only-iam-policies-f373a3471f39?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/f373a3471f39</guid>
            <category><![CDATA[aws-ec2]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-iam]]></category>
            <category><![CDATA[iam-roles]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Tue, 20 Jan 2026 11:29:59 GMT</pubDate>
            <atom:updated>2026-01-20T11:29:59.762Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cA8LqWOvp6RPPgJZ34GA4A.png" /></figure><p>While working through another KodeKloud IAM task, I was asked to create an IAM policy named iampolicy_ravi. The policy needed to allow read-only access to the EC2 console, meaning users could view instances, AMIs, and snapshots, but not change anything.</p><p>I initially thought of the policy as a set of vague rules controlling EC2. That framing wasn’t wrong, but it wasn’t precise either. An IAM policy isn’t just a rule list, it’s a permission contract. It defines exactly what AWS will allow or deny when a request is made.</p><p>In this case, the requirement was read-only access. No starting or stopping instances, no deleting snapshots and no modifying infrastructure. Just visibility. To meet the requirement, the policy used this JSON:</p><pre>{<br>  &quot;Version&quot;: &quot;2012-10-17&quot;,<br>  &quot;Statement&quot;: [<br>    {<br>      &quot;Effect&quot;: &quot;Allow&quot;,<br>      &quot;Action&quot;: [<br>        &quot;ec2:Describe*&quot;<br>      ],<br>      &quot;Resource&quot;: &quot;*&quot;<br>    }<br>  ]<br>}</pre><p>Describe* means you can see everything, but touch nothing. It allows listing and viewing EC2 resources such as instances, AMIs, snapshots, volumes, and security groups. It does not allow creating, modifying or deleting anything.</p><p>At one point, I got confused about the region requirement. The task mentioned us-east-1, but when I tried to change the IAM policy region from global, all regions were disabled. After some research, i found out that IAM policies are global by design. They are not tied to regions the way EC2 resources are. The policy defines <em>what</em> actions are allowed. The region only matters when the permission is used against a service like EC2.</p><p>So even though the EC2 instances live in us-east-1, the policy itself doesn’t live there. It lives at the account level and applies wherever EC2 exists.</p><p>In practice, a policy like this is given to people who need context like developers who are debugging issues, managers who need to understand what infrastructure exists, auditors reviewing configurations or support engineers investigating incidents. These roles need visibility to do their work, but giving them modification rights would introduce unnecessary risk.</p><p>What are the advantages of giving read-only access? It prevents drifts, it allows people to learn the system without being able to damage it and it also creates a clear line between observing and acting.</p><p>If I had to explain it simply, I’d say this: “You can look around the EC2 environment as much as you want, but your hands are tied.”</p><p>Creating the policy took minutes but understanding why it exists took longer. I am still learning, but tasks like this are changing how I think about cloud access and how better im getting at understanding the cloud operations.</p><p>Until the next task, ciao! :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f373a3471f39" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding IAM Groups Through a Simple AWS Migration Task]]></title>
            <link>https://techwriterb.medium.com/understanding-iam-groups-through-a-simple-aws-migration-task-82b472d06d88?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/82b472d06d88</guid>
            <category><![CDATA[iam-roles]]></category>
            <category><![CDATA[cloud-development]]></category>
            <category><![CDATA[aws-migration]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-ec2]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Mon, 19 Jan 2026 14:02:17 GMT</pubDate>
            <atom:updated>2026-01-19T14:02:17.758Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VQF2QStbpLfI0kBzNjLnew.png" /></figure><p>While working through a <a href="https://kodekloud.com/">KodeKloud</a> cloud migration task, i was asked to create an IAM group named iamgroup_jim. At first, i treated it like a setup step and rushed through it. I thought of it as something you do so you can get to the real work later but the task atually represents one of the most important ideas in cloud security.</p><p>Reframed properly, this task was about <strong>preparing a permission boundary for a set of users during a migration</strong>. In cloud environments, especially during migration, access control is where things either stay orderly or spiral. IAM groups exist to make sure that human change does not destabilize systems.</p><p>Initially, i understood the task as simply creating a group so that user accounts can be organized. That wasn’t entirely wrong, but it was shallow. It did not explain why groups exist, why permissions are not attached immediately, or why this matters real in cloud migrations.</p><p>I like to think of it like keys in a school. Every room has a lock. Classrooms, library, staff room, storage, cafetaria etc. Teachers get one key ring, cleaners get another, students and chefs get limited keys. Groups are key rings. If your role changes, your keys change. If you leave the school, your keys gets taken back. IAM simply decides who gets which keys and what doors they can open.</p><p>For this task, we were instructed not to create users or attach permissions, only the group. Permissions are not attached directly to user because you first need to define what the group represents before deciding what access that responsibility requires. With groups, you can update access in one place, and everyone in that group inherits the right permissions.</p><p>As a beginner like myself, there are several mistakes i could make with IAM. Attaching permissions directly to users, giving admin access because it just works, or avoiding roles and groups because they feel abstract. The problem is, these shortcuts turn into confusion, security gaps, and auditing nightmares. If someone with access leaves the company, you’d have to manually hunt down every single permission to revoke it. Groups and roles remove that headache.</p><p>In real companies, IAM groups exist to provide access control during cloud migration, organize humans (not services), prevent permission sprawl and provide readiness for audits and scaling. This is why experienced teams follow a few strict rules:</p><ul><li>Do not assign permissions directly to users</li><li>Teams change, permissions should not</li><li>Auditors care deeply about consistency and traceability</li></ul><p>IAM groups enforce structure where human behavior is unpredictable.</p><p>When responsibilities change, if five people are in a group and one person’s responsibilities change, you don’t modify the original group. hanging it could affect the other members and create confusion or accidental access. Instead, you move that person to a new group that has the permissions they now need, or you assign them a separate role with the appropriate access. This way, the rest of the group keeps their existing permissions, and only the person with new responsibilities gets updated access.</p><p>IAM groups protect you from:</p><ul><li>Inconsistent access</li><li>Human error</li><li>Over-permissioning</li><li>Security gaps that grow over time</li></ul><p>They make access changes predictable. When someone joins, moves, or leaves, you update structure, not individuals.</p><p>The worst misuse of IAM is giving everyone full access just to make things work. This removes isolation, accountability, and safety. One compromised account or careless action can delete systems or expose sensitive data. Admin access for daily work defeats the purpose of IAM entirely and turns the cloud into a single point of failure and unsafe.</p><p>Why does this matter in cloud migration? During a migration, IAM ensures people only access what they’re supposed to. It links job roles to permissions so no one gets accidental access to sensitive resources. Without IAM, access gets messy fast. With IAM, access stays organized, safe, and easy to manage.</p><p>So yeah, the task itself was trivial but the insight behind it is anything but. It’s a small step that teaches a lesson about thoughtfuly designing access control, thinking in terms of roles instead of people, and preparing for scale before you need it. I may have just created a group, but I also learned why groups exist in the first place and that is a far more valuable takeaway than just checking a box.</p><p>I’m still learning, but breaking down these small tasks has already changed how I think about cloud security and access control. I’m looking forward to the next steps in this journey :)</p><p>Until next time, ciao (￣︶￣）</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=82b472d06d88" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Week 5 of Learning Cloud Development]]></title>
            <link>https://techwriterb.medium.com/week-5-of-learning-cloud-development-moving-from-theory-to-hands-on-tasks-015c486aad3d?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/015c486aad3d</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[cloud-development]]></category>
            <category><![CDATA[cloud-devops]]></category>
            <category><![CDATA[ec2]]></category>
            <category><![CDATA[security]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Mon, 05 Jan 2026 12:40:17 GMT</pubDate>
            <atom:updated>2026-01-05T12:40:48.526Z</atom:updated>
            <content:encoded><![CDATA[<p>This week, I moved away from just reading theory and started doing actual hands-on AWS tasks. This was important for me because reading concepts only takes you so far. Things start to click when you touch the tools yourself.</p><p>The first task I was given was to create an <strong>EC2 key pair</strong>. It sounded simple at first, but once I started, I realized there were many words and commands that weren’t explained anywhere. So I decided to break everything down, step by step, in a way that even i could understand.</p><p>This tutorial explains:</p><ul><li>What a key pair is</li><li>Why AWS needs it</li><li>What RSA means</li><li>Why we use AWS CLI commands like STS</li><li>How to create a key pair using the terminal</li></ul><p>If you’re learning cloud from scratch, this is for you.</p><h3>First, What Is an EC2 Key Pair and Why Do We Need It?</h3><p>When you create an EC2 instance, you’re basically creating a virtual server in AWS. Just like a real server, you don’t want random people logging into it.</p><p>AWS uses <strong>key pairs</strong> instead of passwords to make server access more secure.</p><p>A <strong>key pair</strong> has two parts:</p><ul><li><strong>Public key</strong>: Stored by AWS</li><li><strong>Private key</strong>: Downloaded and kept by you</li></ul><p>AWS uses the public key to lock the server. You use the private key to unlock it. If you lose the private key, AWS cannot recover it for you. That’s why this step is taken very seriously.</p><h3>What Does RSA Mean?</h3><p>RSA is a type of <strong>encryption algorithm</strong>. At a very simple level, <strong>encryption</strong> is how data is locked so only the right person can read it and <strong>RSA</strong> is one of the most common and trusted encryption methods.</p><p>When AWS asks for a <strong>key pair type: RSA</strong>, it means: I want my server access keys to use strong, industry-standard encryption.</p><p>You don’t need to know the math behind RSA to use AWS, but you should know that RSA keeps your server access secure, it’s widely supported and it’s safe for beginners to use</p><h3>Task Requirements (What We Were Asked to Do)</h3><p>We were asked to create a key pair with:</p><ul><li><strong>Name:</strong> xfusion-kp</li><li><strong>Key type:</strong> RSA</li><li><strong>Region:</strong> us-east-1 (N. Virginia)</li></ul><p>Everything must be created in that region.</p><h3>Creating the Key Pair Using the AWS CLI</h3><p>This method uses the command line. I’ll explain why each command is needed.</p><h3>Step 1: Get AWS Credentials</h3><p>Before you can talk to AWS, AWS needs to know <strong>who you are</strong> and <strong>what you’re allowed to do</strong>.</p><p>That’s what credentials are for.</p><p>I ran:</p><pre>showcreds</pre><p>This command shows temporary credentials provided for the task:</p><ul><li>Access Key ID</li><li>Secret Access Key</li><li>Session Token</li></ul><p>Think of credentials like a temporary ID card that lets you enter AWS.</p><h3>Step 2: What Is AWS STS and Why Are We Using It?</h3><p>STS stands for <strong>Security Token Service</strong>. AWS STS is used to:</p><ul><li>Verify identity</li><li>Confirm that AWS recognizes your credentials</li><li>Show which account and user you’re logged in as</li></ul><p>I ran:</p><pre>aws sts get-caller-identity</pre><p>This answers the question of who i am according to AWS at that time. If AWS responds with your account and user details, it means your credentials are valid, you’re authenticated and you can proceed safely</p><pre>{<br>“UserId”: “BENEDIO8C21TAONYEBUCHI”,<br>“Account”: “123456789101”,<br>“Arn”: “arn:aws:iam::123456789101:user/bb_labs_user_123456”</pre><h3>Step 3: Setting the AWS Region (Why This Matters)</h3><p>AWS has data centers all over the world. If you don’t specify a region, AWS might create resources in the wrong place.</p><p>Since the task explicitly says <strong>us-east-1</strong>, I set it manually:</p><pre>aws configure set region us-east-1</pre><p>This tells AWS: that any resource I create from now on should live in this region.</p><h3>Step 4: Creating the Key Pair (The Actual Task)</h3><p>Now that authentication and region are set, we can create the key pair.</p><pre>aws ec2 create-key-pair \<br>  --key-name xfusion-kp \<br>  --key-type rsa \<br>  --query &quot;KeyMaterial&quot; \<br>  --output text &gt; xfusion-kp.pem</pre><p>Let’s break this down slowly.</p><ul><li>aws ec2 create-key-pairtells AWS to create a new EC2 key pair.</li><li>--key-name xfusion-kpis simply the name of the key.</li><li>--key-type rsaspecifies the encryption type.</li><li>--query &quot;KeyMaterial&quot;extracts only the private key from the response.</li><li>--output textformats the output as plain text.</li><li>&gt; xfusion-kp.pemsaves the private key into a file on your machine.</li></ul><p>This .pem file is extremely important. It’s the only way you’ll ever access your EC2 instance.</p><h3>Step 5: Why Do We Change File Permissions?</h3><p>Linux systems are strict about file permissions for security reasons.</p><p>AWS will refuse to use your key if it’s too open. So we run:</p><pre>chmod 400 xfusion-kp.pem</pre><p>This means only the file owner can read the key and no one else can access it</p><h3>Final Thoughts</h3><p>Creating a key pair touches security, identity, encryption, and regions all at once.</p><p>By breaking it down, we saw why AWS needs to know who is making a request, why RSA is used, and why regions are not just labels.</p><p>This was just one task, but it made the cloud feel practical and intentional rather than abstract. If you are starting out, understanding this foundation makes everything that comes next easier to reason about.</p><p>On to the next lesson.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=015c486aad3d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Week 4 of Learning Cloud Development: Elastic Load Balancing and Decoupling Services]]></title>
            <link>https://techwriterb.medium.com/week-4-of-learning-cloud-development-elastic-load-balancing-and-decoupling-services-fc913434b717?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/fc913434b717</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[beginners-guide]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[autoscaling]]></category>
            <category><![CDATA[decoupling]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Wed, 26 Nov 2025 19:20:01 GMT</pubDate>
            <atom:updated>2026-02-24T09:55:13.336Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="AI-generated image" src="https://cdn-images-1.medium.com/max/593/1*ux0y4qrdYWccII2NAHZUCQ.png" /><figcaption>AI-generated image describing Elastic load balancing</figcaption></figure><p>I didn’t post anything last week because I was buried in a client project that needed quick delivery. I had to pause my learning for a bit, but I picked things up again this week and decided to continue documenting my cloud journey.</p><p>This week, I spent time understanding how applications handle traffic in AWS and why decoupling systems makes them more stable. I’m still very new to cloud, so I write these notes the same way I try to understand the concepts myself.</p><h3>Directing Traffic with Elastic Load Balancing</h3><p>To understand load balancers, I pictured a small pharmacy during evening rush hour. There are three workers, but fifty customers are all crowded in front of one counter. That one worker would be overwhelmed while the other two stand almost idle.</p><p>A load balancer is the person who steps in and starts directing customers evenly to all three workers so no one gets overloaded.</p><p>That’s exactly what AWS Elastic Load Balancing (ELB) does. It takes incoming requests and spreads them across your EC2 instances. Without a load balancer, users connect directly to individual instances, and you would have to handle routing, scaling, patching, failover, and maintenance yourself.</p><p>With ELB, AWS manages the routing and the behind-the-scenes work for you.</p><p>The <strong>elastic</strong> part means the load balancer scales automatically with traffic. It can increase or decrease capacity without adding extra hourly cost. ELB works with internal and external traffic and supports different routing strategies to keep everything efficient.</p><h3>How Load Balancers Route Traffic</h3><p>Here are the routing methods I learned, still using the pharmacy example:</p><ol><li><strong>Round-robin</strong><br> This rotates customers evenly across workers. Customer 1 goes to Worker A, customer 2 to Worker B, customer 3 to Worker C, then back to A. It keeps the flow balanced with a simple cycle.</li><li><strong>Least connections</strong><br> New customers go to the worker with the fewest people currently in front of them. If Worker A has seven customers, B has three, and C has one, the next customer goes straight to C. This helps when tasks take different amounts of time.</li><li><strong>IP hash</strong><br> This always sends a customer to the same worker based on their ID. In real terms, your IP address decides which server you consistently connect to. It’s useful when a server needs to hold your session information.</li><li><strong>Least response time</strong><br> This sends traffic to the worker responding the fastest at that moment. If Worker A is moving quicker than B and C, the next customer goes to A. It reduces waiting time.</li></ol><p>Load balancers act as a single point of contact for all incoming requests. When paired with <a href="https://medium.com/@benedictacodes/week-3-of-learning-cloud-development-scaling-amazon-ec2-bc749319b96a">Auto Scaling Groups</a> (from Week 3), they keep the application balanced as instances scale in or out, that is, as new instances are added or removed.</p><h3>Messaging and Queuing: Why Decoupling Matters</h3><p>Another concept I learned this week is decoupling systems so one failing component doesn’t break the entire application.</p><p>When components talk directly, the system is <strong>tightly coupled</strong>. If one slows down or fails, everything connected to it is affected.</p><p>Using the pharmacy example again: Imagine two pharmacists standing side by side, passing handwritten notes to each other for every customer request. If one suddenly steps away or gets overwhelmed, the whole process stops because the other depends on immediate responses. Any small issue spreads through the system instantly.</p><p>A <strong>loosely coupled</strong> system fixes this by placing a buffer in the middle. Messages go into a queue and stay there until the receiving service is ready.</p><p>Picture a box between the two pharmacists. Worker A drops messages into the box whenever they are ready. Worker B checks the box whenever they have capacity. Even if B slows down or steps away for a bit, A can keep dropping messages without interruption.</p><p>That box is the message queue.</p><p>It absorbs traffic, protects each component from the other’s delay, and keeps failures from spreading. The sender and receiver no longer need to work at the same speed or even at the same time.</p><p>AWS supports this with:</p><p><strong>Amazon SQS.</strong> Lets components send, store, and receive messages at any volume. Messages sit in a queue (the payload) until the receiving service processes them.</p><p><strong>Amazon SNS.</strong> Sends messages immediately. Instead of storing them, it pushes them out in real time through email, SMS, mobile push, or other delivery methods.</p><p>A simple way that helped me understand:</p><ul><li>SQS places your order on a list. It waits until someone is ready to pick it up.</li><li>SNS is a shout-out. Once it’s made, it goes out immediately.</li></ul><h3>Monolithic vs Microservices Architecture</h3><p>This is part of decoupling as well.</p><p>A <strong>monolithic application</strong> means one large codebase where everything is connected. If one part has issues, you feel it everywhere.</p><p>A <strong>microservices architecture</strong> breaks the system into separate, independent services. They communicate through SQS or SNS and can scale individually. This makes the entire system more resilient and easier to maintain.</p><h3>Closing Thoughts</h3><p>Missing last week stressed me out a bit, but picking up again and learning ELB and decoupling made it worth it. These are concepts I used to see everywhere but never fully understood. Writing them down helps me learn better, and hopefully it helps anyone else who’s starting cloud development from scratch.</p><p>On to the next lesson.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fc913434b717" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Week 3 of Learning Cloud Development: Scaling Amazon EC2]]></title>
            <link>https://techwriterb.medium.com/week-3-of-learning-cloud-development-scaling-amazon-ec2-bc749319b96a?source=rss-57ad158335cd------2</link>
            <guid isPermaLink="false">https://medium.com/p/bc749319b96a</guid>
            <category><![CDATA[amazon-ec2]]></category>
            <category><![CDATA[learning-in-public]]></category>
            <category><![CDATA[tech-journey]]></category>
            <category><![CDATA[cloud-computing-aws]]></category>
            <dc:creator><![CDATA[Benedicta]]></dc:creator>
            <pubDate>Sat, 15 Nov 2025 12:33:11 GMT</pubDate>
            <atom:updated>2026-02-24T09:58:14.825Z</atom:updated>
            <content:encoded><![CDATA[<p>This week pushed me into concepts that felt abstract at first, but the more I read and practiced, the clearer they became. My focus was on how Amazon EC2 handles growth. I explored scalability, elasticity, EC2 Auto Scaling, and the role of Auto Scaling Groups. I had heard these terms before, but this was the first time I understood what they really do and why they matter.</p><h3>Understanding Scalability</h3><p>I learned that scalability describes the system’s ability to support increased workload by adding more resources. It sounds simple, but there are specific ways AWS approaches this.</p><p>There are two methods:</p><ol><li><strong>Scale up (vertical scaling)</strong><br>This means increasing the power of an individual machine. Instead of running an application on a small instance, you move it to a larger instance with more CPU or memory.</li><li><strong>Scale out (horizontal scaling)</strong><br>This involves adding more instances. Instead of upgrading one machine, you run your application across multiple machines that share the workload.</li></ol><p>Scalability is mostly about long-term growth. It ensures that as the user base increases, the system can expand with it without becoming unstable.</p><h3>Understanding Elasticity</h3><p>Elasticity took the scalability idea a bit further. While scalability focuses on growth over time, elasticity focuses on adjusting resources automatically based on real-time demand.</p><p>Traffic goes up, resources go up. Traffic goes down, resources go down. This adjustment happens without manual intervention. It protects performance during high demand and reduces unnecessary cost during low demand.</p><p>Elasticity in AWS is powered by EC2 Auto Scaling.</p><h3>How EC2 Auto Scaling Works</h3><p>EC2 Auto Scaling automatically adds or removes EC2 instances depending on what the system needs at any moment. It does this using metrics collected by Amazon CloudWatch.</p><p>CloudWatch monitors things like CPU usage and latency. Auto Scaling evaluates those metrics and decides whether the application needs more instances or fewer instances.</p><p>There are two main approaches:</p><ol><li><strong>Dynamic scaling</strong><br>This reacts in real time to changes in demand. When the workload increases, new instances launch immediately. When it decreases, the excess instances are terminated.</li><li><strong>Predictive scaling</strong><br>This forecasts future demand based on historical patterns. Instead of waiting for traffic to increase, AWS tries to prepare the right amount of instances beforehand.</li></ol><p>Both approaches help applications remain stable without overspending on resources.</p><h3>Auto Scaling Groups (ASGs)</h3><p>Everything I learned about scaling eventually led back to Auto Scaling Groups. These groups manage collections of EC2 instances that scale together as a unit.</p><p>An ASG depends on three key settings:</p><ol><li><strong>Minimum capacity</strong><br>This is the smallest number of instances the group should ever have. When the group is created, AWS launches this number immediately.</li><li><strong>Desired capacity</strong><br>This is the ideal number of instances needed to handle the current workload. If you do not define this value, AWS uses the minimum capacity as the desired value.</li><li><strong>Maximum capacity</strong><br>This defines the upper limit. Even if demand spikes, the group will never exceed this number, which helps control cost and prevent overscaling.</li></ol><p>For example, if an ASG has a minimum of 4 instances, a desired capacity of 10, and a maximum of 10, the system will run 10 instances during normal operation and will not scale beyond that.</p><h3>What I Took From This Week</h3><p>Before this week, scaling feels more like a system of clear rules reacting to predictable patterns. Understanding how AWS balances performance and cost gave me a better picture of how real applications stay online when traffic fluctuates.</p><p>I am still very new to cloud development, but documenting what I learn each week is helping me understand the concepts in a more practical way. If you are also learning cloud for the first time, I hope this breakdown makes scaling easier to understand.</p><p>On to the next lesson.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*6qoCZX2865ceoLoJSJmxZQ.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bc749319b96a" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>