<?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: TechEazy Consulting</title>
    <description>The latest articles on DEV Community by TechEazy Consulting (@techeazy_consulting).</description>
    <link>https://dev.to/techeazy_consulting</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2041193%2Fa2134f35-95c1-4e56-aa5a-74d5480d53df.jpg</url>
      <title>DEV Community: TechEazy Consulting</title>
      <link>https://dev.to/techeazy_consulting</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/techeazy_consulting"/>
    <language>en</language>
    <item>
      <title>What an AWS Lambda function is, and what its execution role decides</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Tue, 20 Oct 2026 02:26:51 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/what-an-aws-lambda-function-is-and-what-its-execution-role-decides-1g9b</link>
      <guid>https://dev.to/techeazy_consulting/what-an-aws-lambda-function-is-and-what-its-execution-role-decides-1g9b</guid>
      <description>&lt;p&gt;An interviewer leans back and asks, "So what is a Lambda function, really?" You know the slogan: code without servers. Then the follow-up comes: "Your function returns a 502 when it writes to the database. Why?" The slogan does not answer that. This article claims that a fresher can answer both questions with two ideas. First, a Lambda function is a small contract between your code and a runtime that starts, reuses and discards environments for you. Second, the &lt;strong&gt;execution role&lt;/strong&gt; decides everything that code may touch. Most first failures happen because the role and the code disagree, and the article works through the questions in the order an interviewer tends to ask them.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Lambda function is code plus configuration, run only on demand
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The question:&lt;/strong&gt; &lt;em&gt;"What is a Lambda function, in your own words?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A Lambda function is your code plus a few settings that AWS runs only when it is invoked, meaning called. The settings are the runtime, the handler, the memory, the timeout and the role. You never see or patch a machine. AWS creates an environment to run the code in, scales it out when requests arrive together, and throws it away when things go quiet.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think of it as a food stall that only lights its stove when an order arrives.&lt;/em&gt; You write the recipe and pin a few instructions to the wall: which cuisine to cook (the &lt;strong&gt;runtime&lt;/strong&gt;), which recipe card to start from (the &lt;strong&gt;handler&lt;/strong&gt;), and how long a dish may take before it is abandoned (the &lt;strong&gt;timeout&lt;/strong&gt;). The stall owner lights the stove, opens a second stove for a second order, and lets them go cold. You pay per order cooked, not for the stall standing there.&lt;/p&gt;

&lt;p&gt;A strong answer names what this changes. Without a server to keep running, "is the server up?" stops being the hard question. The hard questions become &lt;em&gt;who may call this code&lt;/em&gt;, &lt;em&gt;what may this code touch&lt;/em&gt; and &lt;em&gt;what happened on that one request&lt;/em&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl4t1xj2tbfpiwsqtxd48.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl4t1xj2tbfpiwsqtxd48.png" alt="A request either starts a new environment or reuses one, then the handler runs and returns the response" width="798" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Start-up code runs once per environment; the handler runs once per request&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The handler is a contract that is called once per request
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The question:&lt;/strong&gt; &lt;em&gt;"What does Lambda actually call, and what does it pass in?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lambda calls one function in your code, the &lt;strong&gt;handler&lt;/strong&gt;, once for each request. In Python, a file named &lt;code&gt;lambda_function.py&lt;/code&gt; that defines &lt;code&gt;lambda_handler(event, context)&lt;/code&gt; has the handler &lt;code&gt;lambda_function.lambda_handler&lt;/code&gt;. The &lt;strong&gt;event&lt;/strong&gt; is a document describing what triggered the call. For a web request it holds the method, path, headers and body. The &lt;strong&gt;context&lt;/strong&gt; describes the invocation itself, such as its request ID and its log group name.&lt;/p&gt;

&lt;p&gt;Whatever the handler returns becomes the response. If you return a dictionary with &lt;code&gt;statusCode&lt;/code&gt;, &lt;code&gt;headers&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt;, Lambda turns it into the HTTP response. If you return plain JSON with no status code, Lambda assumes status 200 and content type &lt;code&gt;application/json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Interviewers like the next detail because it shows you understand the lifecycle. Code &lt;em&gt;outside&lt;/em&gt; the handler, such as imports and creating an SDK client, runs once when an environment starts. Later invocations in that same environment reuse it. That is why the Lambda documentation advises creating SDK clients outside the handler: you pay the start-up cost once per environment, not once per request.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think of it as the cook laying out knives before service rather than fetching them for every dish.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Two defaults are worth knowing, and so is how to choose a runtime. A runtime is named by an identifier such as &lt;code&gt;python3.14&lt;/code&gt;, and each identifier has a published deprecation date. When the runtimes page was checked on 2026-10-02, &lt;code&gt;python3.14&lt;/code&gt; was the newest generally available Python runtime. &lt;code&gt;python3.15&lt;/code&gt; was listed as a public preview, which the page says is not for production.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1eny3957oftzeygy435t.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1eny3957oftzeygy435t.png" alt="Runtime, handler, timeout, memory and execution role, each with its default and purpose" width="799" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The settings a function carries, with their defaults and what each one governs&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The execution role is the only thing deciding what your code may touch
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The question:&lt;/strong&gt; &lt;em&gt;"Where does your function get permission to write to the database?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When Lambda runs your code, the code acts &lt;em&gt;as&lt;/em&gt; the execution role. A role is an identity in IAM, the AWS permissions service, and it has two halves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;trust policy&lt;/strong&gt; saying who may take it on, which for an execution role is the Lambda service, &lt;code&gt;lambda.amazonaws.com&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;permission policies&lt;/strong&gt; saying what it may do once it has been taken on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Think of it as a staff badge.&lt;/em&gt; The badge opens the store room and the noticeboard and no other door. The cook did not choose the badge. Whoever hired them did, and the badge is checked at every door.&lt;/p&gt;

&lt;p&gt;The answer that impresses is this one: there are no keys in the code. The Python SDK finds temporary credentials for the role in the function's environment by itself. The Lambda documentation says you do not need to provide credentials to set up a client. If a candidate pastes an access key into a function, it shows they have not understood the 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmz1zzcgthselccjgp278.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmz1zzcgthselccjgp278.png" alt="Lambda assumes the execution role, which may write logs and use one table and nothing else" width="799" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The trust policy lets Lambda take on the role; permission policies decide which doors it opens&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The default role explains the classic 502
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The question:&lt;/strong&gt; &lt;em&gt;"You created a function with every default, and saving a record returns 502. What happened?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the failure a first attempt usually hits. You write a handler that saves a note to a DynamoDB table, which is a managed key-value database. You create the function in the console and accept the defaults. A request returns a bare 502. A status in the 5XX range is what a function URL, the function's public web address, returns when the function itself fails. The response gives no reason.&lt;/p&gt;

&lt;p&gt;The function's log has the reason:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ERROR] ClientError: An error occurred (AccessDeniedException) when calling the PutItem operation:
User: arn:aws:sts::111122223333:assumed-role/hoc-notes-api-role-x1y2/hoc-notes-api is not
authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:ap-south-1:111122223333:table/hoc-notes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code was fine. The console's default option creates a new role with the managed policy &lt;code&gt;AWSLambdaBasicExecutionRole&lt;/code&gt;. That policy grants exactly three actions: &lt;code&gt;logs:CreateLogGroup&lt;/code&gt;, &lt;code&gt;logs:CreateLogStream&lt;/code&gt; and &lt;code&gt;logs:PutLogEvents&lt;/code&gt;. So the function could log its own error, but it could not save the note.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdmar4imk0wdut8y3uwlx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdmar4imk0wdut8y3uwlx.png" alt="The table refuses PutItem, the error goes to the logs, and the caller receives a bare 502" width="799" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The role may write logs but not the table, so the caller sees only 502 while the log names the cause&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Read the error as a sentence. The subject is the role, the verb is the action, and the object is the table. Every permission problem inside a function reads that way, so the fix is always the same: add exactly that action, on exactly that resource, to the role. In the console, that means choosing &lt;strong&gt;Use another role&lt;/strong&gt; under Permissions and picking a role built for read and write on the one table, with basic logging added.&lt;/p&gt;

&lt;p&gt;An interviewer may push: "Why not just attach an administrator policy?" It would make the error go away. It would also mean that a bug in this one function could change anything in the account. In our view, saying that unprompted is one of the clearest signs a fresher has thought about permissions rather than just made them work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who may call the function is a separate decision
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The question:&lt;/strong&gt; &lt;em&gt;"So the role controls who can call it?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No, and this is the trap. The execution role decides what the function may &lt;em&gt;call&lt;/em&gt;. A different policy decides who may &lt;em&gt;invoke&lt;/em&gt; the function: the &lt;strong&gt;resource-based policy&lt;/strong&gt;, which is attached to the function itself.&lt;/p&gt;

&lt;p&gt;The two failures look alike but happen on opposite sides of the function. A 403 from the function URL, with no START line in the log, means the request was refused before your code ran. In that case the resource-based policy is the place to look. An &lt;code&gt;AccessDeniedException&lt;/code&gt; inside the log means the code ran and the role was refused. Being able to tell these apart in one sentence is worth more in an interview than any definition.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8c21gw7ibk3q4bjpmxv0.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8c21gw7ibk3q4bjpmxv0.png" alt="A 403 points to the resource-based policy, AccessDenied to the role, a traceback to the code" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Two permission failures, on opposite sides of the function&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A small notes function shows each idea in a few lines
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The question:&lt;/strong&gt; &lt;em&gt;"Walk me through a function you wrote."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A useful one to describe is a notes API: a single Python handler that lists notes on GET and adds a note on POST. Each line choice answers one of the ideas above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The client is created at module level.&lt;/strong&gt; &lt;code&gt;table = boto3.resource("dynamodb").Table(TABLE_NAME)&lt;/code&gt; sits outside the handler, so each environment pays for it once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The table name comes from an environment variable&lt;/strong&gt;, &lt;code&gt;TABLE_NAME&lt;/code&gt;, with a fallback. The configuration stays out of the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The method is read from the event&lt;/strong&gt;, at &lt;code&gt;event["requestContext"]["http"]["method"]&lt;/code&gt;. A function URL delivers requests in the same &lt;em&gt;payload format version 2.0&lt;/em&gt; shape that Amazon API Gateway uses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The body is decoded when &lt;code&gt;isBase64Encoded&lt;/code&gt; is true.&lt;/strong&gt; That flag means Lambda encoded a binary request body as text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bad input returns 400, not an exception.&lt;/strong&gt; Empty text, invalid JSON or text over 500 characters each get a clear error. An exception reaches the caller only as the opaque 5XX described earlier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;json.dumps(..., default=str)&lt;/code&gt;&lt;/strong&gt; handles DynamoDB numbers. The SDK returns them as Python &lt;code&gt;Decimal&lt;/code&gt; values, which &lt;code&gt;json.dumps&lt;/code&gt; refuses on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;OPTIONS&lt;/code&gt; returns 204&lt;/strong&gt; because browsers send it before some cross-origin calls.&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8sh3nc9iby2owuiwzqon.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8sh3nc9iby2owuiwzqon.png" alt="GET returns 200, a valid POST 201, bad input 400, OPTIONS 204, other methods 405" width="799" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Each kind of request gets a deliberate status code instead of an unhandled failure&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is one honest weakness to mention before the interviewer finds it. The GET handler uses &lt;code&gt;table.scan()&lt;/code&gt;, which reads every item, up to 1 MB per call, and signals when more remains. That is fine for a small table. For a large one it is the wrong tool, and you would design a key you can query by instead. Naming the limit of your own code reads as experience, not weakness.&lt;/p&gt;

&lt;h2&gt;
  
  
  The log is the only witness to a single request
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The question:&lt;/strong&gt; &lt;em&gt;"How would you find out what happened on one failed request?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A function has no screen, so its log is the only record of what one request did. Lambda sends output to CloudWatch Logs, the AWS logging service, as long as the role allows the three &lt;code&gt;logs:&lt;/code&gt; actions. By default the log group is &lt;code&gt;/aws/lambda/&amp;lt;function-name&amp;gt;&lt;/code&gt;, and each environment writes its own stream inside it.&lt;/p&gt;

&lt;p&gt;Every invocation writes START, END and REPORT lines, each carrying the request ID. The REPORT line gives Duration, Billed Duration, Memory Size and Max Memory Used. It also shows Init Duration, but only when a new environment had to start. Anything the code prints appears between START and END.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think of it as the stall's order book: one entry per order, written whether the dish came out right or not.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What to practise before the interview
&lt;/h2&gt;

&lt;p&gt;Practise these until you can say each one aloud without notes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Explain the handler contract, including what runs once per environment and what runs once per request.&lt;/li&gt;
&lt;li&gt;Name the two halves of an execution role and what &lt;code&gt;AWSLambdaBasicExecutionRole&lt;/code&gt; allows.&lt;/li&gt;
&lt;li&gt;Read an &lt;code&gt;AccessDeniedException&lt;/code&gt; as subject, verb and object, then state the exact fix.&lt;/li&gt;
&lt;li&gt;Separate a 403 with no START line from an AccessDenied inside the log.&lt;/li&gt;
&lt;li&gt;Defend one design choice in your own function, and name one of its limits.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ul&gt;
&lt;li&gt;A Lambda function is code plus configuration that runs on demand. The handler is called once per request, and code outside it runs once per environment.&lt;/li&gt;
&lt;li&gt;The execution role decides what the code may touch. Its trust policy names &lt;code&gt;lambda.amazonaws.com&lt;/code&gt;, and the code holds no keys.&lt;/li&gt;
&lt;li&gt;The default role can only write logs. That is why a first database write often fails with a bare 5XX.&lt;/li&gt;
&lt;li&gt;Fix permission errors with exactly the missing action on exactly that resource, never with broad access.&lt;/li&gt;
&lt;li&gt;Who may &lt;em&gt;call&lt;/em&gt; the function is decided by a separate resource-based policy, and the log tells you which side refused.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article does not settle how to authenticate callers properly, how to configure CORS (the headers that let a browser page read the function's responses), or what any of this costs at scale. Each of those is a decision in its own right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full article: &lt;a href="https://techeazyconsulting.com/what-an-aws-lambda-function-is-and-what-its-execution-role-decides" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/what-an-aws-lambda-function-is-and-what-its-execution-role-decides&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Full chapter: &lt;a href="https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-07" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-07&lt;/a&gt;
&amp;lt;!-- cf-origin:end --&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Creating your first key-value table from the command line, and measuring what each read costs</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Mon, 19 Oct 2026 07:05:37 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/creating-your-first-key-value-table-from-the-command-line-and-measuring-what-each-read-costs-5b4n</link>
      <guid>https://dev.to/techeazy_consulting/creating-your-first-key-value-table-from-the-command-line-and-measuring-what-each-read-costs-5b4n</guid>
      <description>&lt;p&gt;You have a small notes app and nowhere permanent to keep the notes. Records stored on a server's own disk vanish when that server is replaced, so you want a managed table that outlives any one machine. You open a terminal and immediately hit two questions: what should the first command be, and how do you know whether a read is cheap or expensive?&lt;/p&gt;

&lt;p&gt;This lab answers both using Amazon DynamoDB, a managed table service you reach entirely through an API. The claim is simple. &lt;strong&gt;The partition key you choose when you create the table decides two things: which item every write touches, and how much work every read does.&lt;/strong&gt; Reading by key goes straight to one item. A Scan reads every item, and you can watch the difference in the response itself. You will create a table, fill it, read it three ways, compare the cost of each, and then delete it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup is small: one identity, one Region, one billing mode
&lt;/h2&gt;

&lt;p&gt;You need an account, an everyday administrator identity that is not the root user, and the AWS command-line interface (CLI), version 2, signed in as that identity. This lab uses the Asia Pacific (Mumbai) Region, &lt;code&gt;ap-south-1&lt;/code&gt;. If your CLI is not yet set to that Region, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure &lt;span class="nb"&gt;set &lt;/span&gt;region ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm who you are signed in as, run &lt;code&gt;aws sts get-caller-identity&lt;/code&gt;. The &lt;code&gt;Account&lt;/code&gt; field in the output is your 12-digit account ID. The CLI documentation notes that this command needs no permissions, so it works whatever identity you use.&lt;/p&gt;

&lt;p&gt;Now the money. The table uses &lt;strong&gt;on-demand capacity&lt;/strong&gt;, a mode in which you pay per read and write request and plan no capacity in advance. The service documentation calls it the default and recommended mode. It also states that if you are "driving zero traffic to your table, then with on-demand, you are not charged for any throughput." Storage is billed separately.&lt;/p&gt;

&lt;p&gt;As of 2026-10-02, the pricing page listed 25 GB of storage per Region in the Free Tier. It also listed 25 free read and 25 free write capacity units, but those apply to the &lt;em&gt;provisioned&lt;/em&gt; mode, not to on-demand requests. The few dozen requests in this lab are billed per request.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqbajo9m5d9ouhp75q57i.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqbajo9m5d9ouhp75q57i.png" alt="Table listing which on-demand table costs are billed: requests and storage yes, idle throughput no" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;On-demand bills each request and stored data; an idle table has no throughput charge&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The partition key is the first decision, because it is the item's identity
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;table&lt;/strong&gt; is a collection of &lt;strong&gt;items&lt;/strong&gt;, much like rows. Each item is a group of &lt;strong&gt;attributes&lt;/strong&gt;, much like fields. Every item must have a &lt;strong&gt;primary key&lt;/strong&gt; that no other item shares. In the simplest case that key is one attribute, the &lt;strong&gt;partition key&lt;/strong&gt;. DynamoDB feeds the partition key's value into an internal hash function, and the result decides where the item is stored.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think of it as a wall of numbered lockers.&lt;/em&gt; The table is the wall, and the partition key is the number on each door. To fetch something, you name the number and walk straight to that locker.&lt;/p&gt;

&lt;p&gt;This lab's table is &lt;code&gt;hoc-notes&lt;/code&gt;, with partition key &lt;code&gt;noteId&lt;/code&gt;, a string, and no sort key. Create it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb create-table &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--attribute-definitions&lt;/span&gt; &lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noteId,AttributeType&lt;span class="o"&gt;=&lt;/span&gt;S &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--key-schema&lt;/span&gt; &lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noteId,KeyType&lt;span class="o"&gt;=&lt;/span&gt;HASH &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--billing-mode&lt;/span&gt; PAY_PER_REQUEST &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nv"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;project,Value&lt;span class="o"&gt;=&lt;/span&gt;hands-on-cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three parts of that command do the teaching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--attribute-definitions&lt;/code&gt; lists &lt;strong&gt;only&lt;/strong&gt; the key. You never declare &lt;code&gt;title&lt;/code&gt; or &lt;code&gt;body&lt;/code&gt;. Apart from the key, the table is &lt;em&gt;schemaless&lt;/em&gt;, which means each item can carry different attributes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;KeyType=HASH&lt;/code&gt; marks &lt;code&gt;noteId&lt;/code&gt; as the partition key. The older name for the partition key is "hash attribute", after the hash function. A sort key would be &lt;code&gt;RANGE&lt;/code&gt;. A key attribute must be a string, a number or binary.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PAY_PER_REQUEST&lt;/code&gt; selects on-demand capacity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why choose &lt;code&gt;noteId&lt;/code&gt; and not &lt;code&gt;title&lt;/code&gt;? Because the app fetches a note by its id, from a link or an API path, and because the key must be unique. Titles repeat. As the next sections show, two notes that share a key do not coexist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; the command returns at once with &lt;code&gt;"TableStatus": "CREATING"&lt;/code&gt;. Check it until it changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb describe-table &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Table.TableStatus"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it prints &lt;code&gt;"ACTIVE"&lt;/code&gt;, the table is ready for writes.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F44r1ft3gp40jj9ugdoss.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F44r1ft3gp40jj9ugdoss.png" alt="Writing or reading by noteId passes the key through the hash function to one storage location" width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The partition key's value goes through a hash function that decides where each item is stored&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Items are written in typed JSON, and a reused key replaces silently
&lt;/h2&gt;

&lt;p&gt;The CLI writes items in &lt;strong&gt;typed JSON&lt;/strong&gt;: every value is wrapped in its type. A string is &lt;code&gt;{"S": "Buy milk"}&lt;/code&gt;. The number 2 is &lt;code&gt;{"N": "2"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That number sits inside quotes. It looks wrong the first time, but it is correct. The &lt;code&gt;N&lt;/code&gt; says the value is a number, and the value itself travels as a string. Writing &lt;code&gt;{"N": 2}&lt;/code&gt; is the mistake to watch for.&lt;/p&gt;

&lt;p&gt;Add a few notes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb put-item &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--item&lt;/span&gt; &lt;span class="s1"&gt;'{"noteId": {"S": "n-001"}, "title": {"S": "Buy milk"}, "body": {"S": "Two litres"}}'&lt;/span&gt;

aws dynamodb put-item &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--item&lt;/span&gt; &lt;span class="s1"&gt;'{"noteId": {"S": "n-002"}, "title": {"S": "Read chapter 3"}, "priority": {"N": "2"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add two or three more, each with its own id. Notice that &lt;code&gt;n-002&lt;/code&gt; has a &lt;code&gt;priority&lt;/code&gt; attribute and &lt;code&gt;n-001&lt;/code&gt; does not. That is schemaless storage at work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think of it as your phone's contacts list.&lt;/em&gt; Some contacts have a birthday, some have an email address, and only the ID is required.&lt;/p&gt;

&lt;p&gt;Now try the failure on purpose. Write &lt;code&gt;n-001&lt;/code&gt; again with different contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb put-item &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--item&lt;/span&gt; &lt;span class="s1"&gt;'{"noteId": {"S": "n-001"}, "title": {"S": "Call home"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; nothing. There is no error and no warning.&lt;/p&gt;

&lt;p&gt;Read the item back and it says &lt;code&gt;Call home&lt;/code&gt;, and it has no &lt;code&gt;body&lt;/code&gt; at all. The documentation describes a put precisely: it "creates a new item, or replaces an existing item with a new item." Two writes with the same key are two versions of &lt;strong&gt;one&lt;/strong&gt; item. The second replaces the first entirely, attributes and all. In the locker picture, you did not add a second locker. You emptied the existing one and refilled 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6r32na8wgn6k0djkuhl6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6r32na8wgn6k0djkuhl6.png" alt="A second put with key n-001 succeeds silently and the later read returns only Call home" width="799" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Two puts with the same key leave one item: the second replaces the first entirely&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  GetItem reads one item, because it walks straight to the key
&lt;/h2&gt;

&lt;p&gt;The notes app has two different jobs. Opening a link to one note means the app knows the key. Showing the home page means it must list every note and knows no key. Each job calls for a different read, so measure both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GetItem&lt;/strong&gt; takes the full primary key and returns that one item, or nothing. Ask it to report what it consumed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb get-item &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--key&lt;/span&gt; &lt;span class="s1"&gt;'{"noteId": {"S": "n-002"}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--return-consumed-capacity&lt;/span&gt; TOTAL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; the item, plus a &lt;code&gt;ConsumedCapacity&lt;/code&gt; block that shows the read capacity this one request used. Write that figure down, because it is your baseline.&lt;/p&gt;

&lt;p&gt;Reads are eventually consistent by default. Add &lt;code&gt;--consistent-read&lt;/code&gt; and you get a strongly consistent read instead. It reflects every write that completed before it, and it costs twice as much. Run the command once with the flag and compare the two &lt;code&gt;ConsumedCapacity&lt;/code&gt; figures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scan reads every item, and a filter does not make it cheaper
&lt;/h2&gt;

&lt;p&gt;For the home page there is no key to walk to. You open every locker on the wall, one after another. That is a &lt;strong&gt;Scan&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb scan &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="nt"&gt;--return-consumed-capacity&lt;/span&gt; TOTAL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; all your notes, a &lt;code&gt;ConsumedCapacity&lt;/code&gt; block, and two counts. &lt;code&gt;ScannedCount&lt;/code&gt; is the number of items read. &lt;code&gt;Count&lt;/code&gt; is the number of items returned. On an unfiltered Scan the two are equal.&lt;/p&gt;

&lt;p&gt;Now ask for just one note through a filter. A &lt;strong&gt;filter expression&lt;/strong&gt; narrows the results that come back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb scan &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--filter-expression&lt;/span&gt; &lt;span class="s2"&gt;"title = :t"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--expression-attribute-values&lt;/span&gt; &lt;span class="s1"&gt;'{":t": {"S": "Call home"}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--return-consumed-capacity&lt;/span&gt; TOTAL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; &lt;code&gt;Count&lt;/code&gt; drops to 1, but &lt;code&gt;ScannedCount&lt;/code&gt; still equals the full number of notes. The documentation spells out why: "a &lt;code&gt;Scan&lt;/code&gt; consumes the same amount of read capacity, regardless of whether a filter expression is present." The filter is applied &lt;em&gt;after&lt;/em&gt; the read. It shrinks the answer, not the work. It is like opening every locker and keeping only the red bags.&lt;/p&gt;

&lt;p&gt;Scans also run in pages. A Scan reads up to 1 MB per request, and the CLI keeps requesting pages until it has read the whole table.&lt;/p&gt;

&lt;p&gt;A large &lt;code&gt;ScannedCount&lt;/code&gt; beside a small &lt;code&gt;Count&lt;/code&gt; is the signature of an inefficient read. With five notes the waste is invisible. With a million notes, a Scan that finds one title reads a million items, while GetItem by key still reads one. On-demand capacity bills you for what is read, so this is a cost problem as well as a speed problem.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0xp7wdai4py3759rfmjb.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0xp7wdai4py3759rfmjb.png" alt="GetItem goes from key to one read; a filtered Scan reads all items, then filters, then returns fewer" width="800" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GetItem reads only the named item; a filtered Scan reads every item and returns fewer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my view, the working rule follows directly. Choose Scan when you truly need every item and the table is small, such as listing a practice app's notes. Choose GetItem whenever you can name the key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Query matches GetItem here, and earns its place with a sort key
&lt;/h2&gt;

&lt;p&gt;There is a third read. &lt;strong&gt;Query&lt;/strong&gt; returns the items that share one partition key value. Its key condition must test the partition key for equality, with the value passed through a placeholder that starts with a colon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb query &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--key-condition-expression&lt;/span&gt; &lt;span class="s2"&gt;"noteId = :id"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--expression-attribute-values&lt;/span&gt; &lt;span class="s1"&gt;'{":id": {"S": "n-002"}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--return-consumed-capacity&lt;/span&gt; TOTAL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; one item. In a table with only a partition key, no two items can share that value, so Query returns at most one item, the same one GetItem returns.&lt;/p&gt;

&lt;p&gt;Query earns its place when a table also has a &lt;strong&gt;sort key&lt;/strong&gt;, an optional second key attribute. Items that share a partition key are stored together, ordered by the sort key. Picture a music table keyed by artist and song title. Querying one artist is like pulling out the drawer with that artist's name: every song comes out in title order, and no other drawer is touched.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdqzwqmn4336pjo8octou.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdqzwqmn4336pjo8octou.png" alt="Card comparing GetItem, Query and Scan by what you must know and how many items each reads" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The three reads differ in what you must know and how much they read&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleaning up leaves nothing to bill
&lt;/h2&gt;

&lt;p&gt;An idle on-demand table incurs no throughput charge, but its stored data is still billed. When you have finished experimenting, delete the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb delete-table &lt;span class="nt"&gt;--table-name&lt;/span&gt; hoc-notes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; a description of the table with its status changing to &lt;code&gt;DELETING&lt;/code&gt;. After that, &lt;code&gt;describe-table&lt;/code&gt; reports that the table cannot be found. The &lt;code&gt;project = hands-on-cloud&lt;/code&gt; tag you added at creation makes it easy to check that nothing from this lab is left behind.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Create the table with only its key declared. Everything else is schemaless and can differ from item to item.&lt;/li&gt;
&lt;li&gt;Choose the partition key from how the data is fetched and what makes it unique, such as an id and never a title. A put with an existing key silently replaces the whole item.&lt;/li&gt;
&lt;li&gt;Write values in typed JSON, and quote numbers: &lt;code&gt;{"N": "2"}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;--return-consumed-capacity TOTAL&lt;/code&gt; to any read to see what it cost. Compare &lt;code&gt;ScannedCount&lt;/code&gt; with &lt;code&gt;Count&lt;/code&gt; on every Scan.&lt;/li&gt;
&lt;li&gt;GetItem reads one item. A Scan reads all of them, and a filter expression does not reduce what it reads.&lt;/li&gt;
&lt;li&gt;On on-demand capacity you pay for requests and stored data. Strongly consistent reads cost twice as much as the default.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lab measured reads on a handful of items. It does not settle how to design keys for richer access patterns, how to prevent overwrites with a condition on the put, or how to limit an application's permissions to this one table. Each of those deserves its own treatment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full article: &lt;a href="https://techeazyconsulting.com/creating-your-first-key-value-table-from-the-command-line-and-measuring-what-each-read-costs" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/creating-your-first-key-value-table-from-the-command-line-and-measuring-what-each-read-costs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Full chapter: &lt;a href="https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-06" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-06&lt;/a&gt;
&amp;lt;!-- cf-origin:end --&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Signing the AWS CLI in without access keys, then proving a policy in the simulator</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Fri, 16 Oct 2026 09:40:25 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/signing-the-aws-cli-in-without-access-keys-then-proving-a-policy-in-the-simulator-5ed7</link>
      <guid>https://dev.to/techeazy_consulting/signing-the-aws-cli-in-without-access-keys-then-proving-a-policy-in-the-simulator-5ed7</guid>
      <description>&lt;p&gt;You have just installed the AWS CLI, and the setup guide asks you to paste in an access key ID and secret. That leaves a long-lived secret sitting in a file on your laptop. Next you need a permissions policy, and you have no way to know whether it does what you meant until something breaks.&lt;/p&gt;

&lt;p&gt;This lab shows that neither step needs that risk. The &lt;code&gt;aws login&lt;/code&gt; command exchanges an ordinary console sign-in for temporary credentials that the CLI manages for you. The IAM policy simulator then tells you whether a policy would allow or deny an action, without sending a real request to any service. Together they let you work from the terminal with no stored keys, and check a policy before it can do any harm. The simulator is a rehearsal, not a guarantee, and this lab is explicit about where it stops.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal, and the three tasks that reach it
&lt;/h2&gt;

&lt;p&gt;The lab has three tasks, in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign the CLI in without an access key, and confirm who it is acting as.&lt;/li&gt;
&lt;li&gt;Write a policy and prove its behaviour in the simulator.&lt;/li&gt;
&lt;li&gt;Find where the session is stored, look at it, and delete it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The order matters. Every simulator command in task 2 is itself an AWS CLI call, so it needs the credentials from task 1. Task 3 tidies away what task 1 created.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4zzfkdkqm664716mfzjs.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4zzfkdkqm664716mfzjs.png" alt="Four steps in order: sign in, simulate a policy, inspect the stored session, sign out" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sign in first, simulate with that session, then delete it&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 2.32.0 is the floor for signing in without keys
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;aws login&lt;/code&gt; command needs AWS CLI version 2.32.0 or later. This lab is written against version 2.38.1, the current release, which is well past that floor. Confirm what you have installed with the global &lt;code&gt;--version&lt;/code&gt; option:&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="nv"&gt;$ &lt;/span&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need an identity that can sign in to the AWS Management Console. That can be the root user, an IAM user, or a federated identity from your identity provider. If your organisation uses IAM Identity Center, a separate configuration path applies instead.&lt;/p&gt;

&lt;p&gt;The identity also needs permission to use this sign-in method. Attach the &lt;code&gt;SignInLocalDevelopmentAccess&lt;/code&gt; managed policy to the IAM user, role or group. Root users need no extra permissions.&lt;/p&gt;

&lt;p&gt;On a shared account, signing in as root to complete a lab is a poor habit. A sensible default is an IAM user or a federated identity that carries the managed policy above.&lt;/p&gt;

&lt;h2&gt;
  
  
  aws login turns a console sign-in into temporary credentials
&lt;/h2&gt;

&lt;p&gt;Run the command 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;&lt;span class="nv"&gt;$ &lt;/span&gt;aws login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To sign in to a named profile, or to create one, add &lt;code&gt;--profile&lt;/code&gt;:&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="nv"&gt;$ &lt;/span&gt;aws login &lt;span class="nt"&gt;--profile&lt;/span&gt; my-dev-profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the profile is new, or no Region is set, the CLI asks for an AWS Region and offers &lt;code&gt;us-east-1&lt;/code&gt; as the default. You can change the Region later with &lt;code&gt;aws configure set region NEW_REGION&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The CLI then tries to open your default browser on the sign-in page. You can pick one of your active console sessions or sign in afresh. In the browser, choose the credentials to use, then return to the terminal.&lt;/p&gt;

&lt;p&gt;Suppose the profile already holds a different session. For example, it was set up as a read-only user and you have now signed in as an admin user. The CLI asks whether to overwrite the existing session, and it waits for a y or n. A final message confirms the completed profile configuration.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F90b6n6u0xjqd601pxd3c.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F90b6n6u0xjqd601pxd3c.png" alt="You run aws login, sign in through the browser, and the CLI caches temporary credentials" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The browser proves who you are; the CLI keeps temporary credentials&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The command still works on a machine with no browser, such as a remote server. Use &lt;code&gt;aws login --remote&lt;/code&gt; and the CLI prints a URL to open on another device. After you sign in there, you copy the authorization code back into the CLI prompt.&lt;/p&gt;

&lt;p&gt;You can also control which of the two flows is allowed. The two flows have separate resource ARNs that you can use in IAM policies:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxzdrkbf1l516e1j3lxub.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxzdrkbf1l516e1j3lxub.png" alt="aws login uses the localhost ARN; aws login --remote uses the remote ARN" width="799" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Same-device and cross-device sign-in each have their own ARN to allow or deny&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  get-caller-identity proves who the CLI now is
&lt;/h2&gt;

&lt;p&gt;Before you trust the session, ask AWS who you are:&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="nv"&gt;$ &lt;/span&gt;aws sts get-caller-identity
&lt;span class="nv"&gt;$ &lt;/span&gt;aws sts get-caller-identity &lt;span class="nt"&gt;--profile&lt;/span&gt; my-dev-profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command uses the default profile. The second uses a named one. You should see the identity you chose in the browser.&lt;/p&gt;

&lt;p&gt;The credentials then look after themselves. The CLI and SDKs refresh the cached credentials every 15 minutes as needed. The whole session lasts up to the IAM principal's set session duration, to a maximum of 12 hours, after which you run &lt;code&gt;aws login&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;Think of it as a day pass that renews itself at the turnstile, rather than a key you cut and carry forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  The simulator answers "allowed or denied" without touching anything
&lt;/h2&gt;

&lt;p&gt;The IAM policy simulator evaluates a request against the policies you give it. It never sends that request to any AWS service. For every action and resource you test, it returns one of two outcomes: allowed or denied. When the outcome is an allow or an explicit deny, it also names the policy statement that produced it.&lt;/p&gt;

&lt;p&gt;The simulator has two modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Principal mode&lt;/strong&gt; tests the policies already attached to an existing user, role or group.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom mode&lt;/strong&gt; tests policies that you write or paste in. Nothing is saved to your account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Custom mode is the one to use when checking a draft before you attach it. On the command line, custom mode is &lt;code&gt;aws iam simulate-custom-policy&lt;/code&gt;. Policies already attached to an identity use &lt;code&gt;simulate-principal-policy&lt;/code&gt; instead.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzt6by7w7a3ngf3pwfibu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzt6by7w7a3ngf3pwfibu.png" alt="Policies, actions, resources and context values go into the simulator, which returns one of three decisions" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The simulator weighs policies and inputs, then returns a decision and no service response&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A custom policy is proved with one command and a context value
&lt;/h2&gt;

&lt;p&gt;Here is the draft policy. It allows every DynamoDB action, but only after a set date and time. The command below simulates the &lt;code&gt;dynamodb:CreateBackup&lt;/code&gt; action and supplies a value for the &lt;code&gt;aws:CurrentTime&lt;/code&gt; key that the condition checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws iam simulate-custom-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-input-list&lt;/span&gt; &lt;span class="s1"&gt;'{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":"dynamodb:*","Resource":"*","Condition":{"DateGreaterThan":{"aws:CurrentTime":"2018-08-16T12:00:00Z"}}}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--action-names&lt;/span&gt; dynamodb:CreateBackup &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--context-entries&lt;/span&gt; &lt;span class="s2"&gt;"ContextKeyName='aws:CurrentTime',ContextKeyValues='2019-04-25T11:00:00Z',ContextKeyType=date"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The supplied date is later than the condition's date. The result therefore shows &lt;code&gt;"EvalDecision": "allowed"&lt;/code&gt;, and its &lt;code&gt;MatchedStatements&lt;/code&gt; entry points to &lt;code&gt;PolicyInputList.1&lt;/code&gt;, the first policy you passed in.&lt;/p&gt;

&lt;p&gt;A passing test proves little on its own. Now prove that the condition actually bites by changing the context value to &lt;code&gt;2014-04-25T11:00:00Z&lt;/code&gt;, a date before the one the policy requires. The decision becomes &lt;code&gt;implicitDeny&lt;/code&gt;, and &lt;code&gt;MatchedStatements&lt;/code&gt; is empty.&lt;/p&gt;

&lt;p&gt;Two allowed actions on their own would not show that the condition works. A passing case alongside a failing one does. In practice, a sensible habit is to write one test that should pass and one that should fail for every condition you care about.&lt;/p&gt;

&lt;p&gt;A few rules for the inputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Action names must include the service prefix, such as &lt;code&gt;iam:CreateUser&lt;/code&gt;, and wildcards are not allowed.&lt;/li&gt;
&lt;li&gt;If you leave out &lt;code&gt;--resource-arns&lt;/code&gt;, the resource defaults to &lt;code&gt;*&lt;/code&gt;, meaning all resources.&lt;/li&gt;
&lt;li&gt;The resources you name do not need to exist in your account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reading the result: the decision, the statement, the missing keys
&lt;/h2&gt;

&lt;p&gt;Each result carries an &lt;code&gt;EvalDecision&lt;/code&gt; with one of three values. When several statements apply, one explicit deny overrides any number of allows, and only the deny statement appears in the result.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv6mi4l3fw02ve57tl2k8.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv6mi4l3fw02ve57tl2k8.png" alt="allowed and explicitDeny name a statement; implicitDeny matches none" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Two ways to be denied, and only one of them names a statement&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Also watch &lt;code&gt;MissingContextValues&lt;/code&gt;. It lists the context keys your policies need but that you did not supply. If a supplied value does not satisfy a condition, the action is denied.&lt;/p&gt;

&lt;p&gt;The simulator fills in some keys by itself. These are the principal keys, such as &lt;code&gt;aws:PrincipalAccount&lt;/code&gt; and &lt;code&gt;aws:UserName&lt;/code&gt;, and organisation keys such as &lt;code&gt;aws:PrincipalOrgID&lt;/code&gt;. You supply every other key yourself. To find out which keys a draft policy needs before you run it, the CLI reference points to &lt;code&gt;GetContextKeysForCustomPolicy&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Several resources now come back as one aggregate answer
&lt;/h2&gt;

&lt;p&gt;In version 2.38.1, the simulator returns a single evaluation result per action, however many resource ARNs you pass. Older behaviour returned one result per resource, each carrying the same overall decision.&lt;/p&gt;

&lt;p&gt;The top-level &lt;code&gt;EvalDecision&lt;/code&gt; is now the most restrictive decision across all resources. If any resource produces &lt;code&gt;explicitDeny&lt;/code&gt;, the top-level decision is &lt;code&gt;explicitDeny&lt;/code&gt;. To see the decision for each resource, read &lt;code&gt;ResourceSpecificResults&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This affects how you read the output. The top-level &lt;code&gt;EvalResourceName&lt;/code&gt; is now an ARN template for the resource type, not one of your ARNs. Any script that parsed per-resource answers from the top level needs to read &lt;code&gt;ResourceSpecificResults&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Some features have limits worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can include only one resource-based policy per simulation.&lt;/li&gt;
&lt;li&gt;The simulator never fetches a resource's policy for you, so you must pass it in.&lt;/li&gt;
&lt;li&gt;Simulating resource-based policies is not supported for IAM roles.&lt;/li&gt;
&lt;li&gt;Service control policies can be passed in order, from the organisation root down to the account. Their matched statements are not shown in the results, for security reasons.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cleaning up: where the session lives, how to look at it, how to delete it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Where it is stored.&lt;/strong&gt; Signing in with the default profile writes a &lt;code&gt;login_session&lt;/code&gt; line to the &lt;code&gt;config&lt;/code&gt; file. That line holds your identity's ARN, next to the Region. The temporary credentials, and the details needed to refresh them, are cached in &lt;code&gt;~/.aws/login/cache&lt;/code&gt; on Linux and macOS, or &lt;code&gt;%USERPROFILE%\.aws\login\cache&lt;/code&gt; on Windows. The &lt;code&gt;AWS_LOGIN_CACHE_DIRECTORY&lt;/code&gt; environment variable moves that cache to another location.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Look at it.&lt;/strong&gt; Open the &lt;code&gt;config&lt;/code&gt; file and find the &lt;code&gt;login_session&lt;/code&gt; entry for your profile. List the cache directory too; its file names are based on the resolved profile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delete it.&lt;/strong&gt; You can let the credentials expire, or remove them now:&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="nv"&gt;$ &lt;/span&gt;aws &lt;span class="nb"&gt;logout&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;aws &lt;span class="nb"&gt;logout&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; my-dev-profile
&lt;span class="nv"&gt;$ &lt;/span&gt;aws &lt;span class="nb"&gt;logout&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With no profile on the command line or in &lt;code&gt;AWS_PROFILE&lt;/code&gt;, &lt;code&gt;aws logout&lt;/code&gt; signs out the default profile. The &lt;code&gt;--all&lt;/code&gt; option signs out every profile that uses login credentials.&lt;/p&gt;

&lt;p&gt;The policy work needs no cleanup. Custom-mode policies are never saved to your account, and editing a policy inside the simulator leaves the real one unchanged.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqdapzbth2m68p8wivllw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqdapzbth2m68p8wivllw.png" alt="aws login writes the config entry and the cache; you inspect both, then aws logout deletes the cached credentials" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A login session is written to two places and removed by one command&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;aws login&lt;/code&gt; needs CLI version 2.32.0 or later. It swaps a console sign-in for temporary credentials that refresh themselves for up to 12 hours, so no long-lived key is stored on disk.&lt;/li&gt;
&lt;li&gt;Confirm the session with &lt;code&gt;aws sts get-caller-identity&lt;/code&gt; before you rely on it.&lt;/li&gt;
&lt;li&gt;Prove a draft policy in custom mode with &lt;code&gt;simulate-custom-policy&lt;/code&gt;. Pair a case that should pass with one that should fail, and supply every context key the conditions check.&lt;/li&gt;
&lt;li&gt;In version 2.38.1, read per-resource decisions from &lt;code&gt;ResourceSpecificResults&lt;/code&gt;; the top-level decision is an aggregate of all resources.&lt;/li&gt;
&lt;li&gt;Clean up with &lt;code&gt;aws logout&lt;/code&gt;. Simulated policies leave nothing behind in your account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The limit is the one the simulator states about itself: its results can differ from your live environment. It does not evaluate resource control policies. It can also diverge on VPC endpoint policies, role chaining, or resources that have several resource-based policies. A simulated "allowed" is strong evidence, not proof. This lab does not cover the final check: confirming the attached policy's behaviour against your live account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full article: &lt;a href="https://techeazyconsulting.com/signing-the-aws-cli-in-without-access-keys-then-proving-a-policy-in-the-simulator" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/signing-the-aws-cli-in-without-access-keys-then-proving-a-policy-in-the-simulator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Full chapter: &lt;a href="https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-02" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-02&lt;/a&gt;
&amp;lt;!-- cf-origin:end --&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to find the closed port that stops an EC2 web page loading, and lock down SSH</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Fri, 16 Oct 2026 03:24:08 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/how-to-find-the-closed-port-that-stops-an-ec2-web-page-loading-and-lock-down-ssh-mgk</link>
      <guid>https://dev.to/techeazy_consulting/how-to-find-the-closed-port-that-stops-an-ec2-web-page-loading-and-lock-down-ssh-mgk</guid>
      <description>&lt;p&gt;You launched an Amazon EC2 instance, installed a web server, and typed its public address into a browser. The tab spins and then times out. Nothing on the server looks broken, and the cause is outside the server. In almost every first attempt, the block is the instance's &lt;strong&gt;security group&lt;/strong&gt;, the virtual firewall that sits in front of it. This article argues that two changes fix the problem and make the instance safer. First, open only ports 80 and 443 to the world. Second, close SSH to everyone except you, and use EC2 Instance Connect so you stop handing out keys. The steps below cover where to look, what each rule should say, what you should see afterwards, and what to remove when you finish.&lt;/p&gt;

&lt;h2&gt;
  
  
  The page times out because no inbound rule admits web traffic
&lt;/h2&gt;

&lt;p&gt;A security group acts as a virtual firewall for your EC2 instances and controls incoming and outgoing traffic. Inbound rules control the traffic coming in to your instance, and outbound rules control the traffic going out. The only traffic that reaches the instance is the traffic the security group rules allow.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think of it as a guest list at a door.&lt;/em&gt; Nobody gets in unless the list names them. A browser asking for your page is a guest the list does not yet name. The web server process may be running perfectly, but the request is turned away before it reaches the server.&lt;/p&gt;

&lt;p&gt;This also explains why the failure usually shows up as a timeout rather than an error page. In practice, a request the firewall drops never gets a reply, so the browser waits until it gives up. If you see a slow timeout instead of an immediate refusal, a missing rule is the first thing to check.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsihh1nwwbh1ripru3wm7.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsihh1nwwbh1ripru3wm7.png" alt="A request passes the security group to the web server only when a matching inbound rule exists" width="799" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A browser request reaches the web server only if a security group rule allows it&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Read every security group on the instance, not just one
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; find out which rules actually apply to your instance.&lt;/p&gt;

&lt;p&gt;You can associate an instance with several security groups, and you can associate one security group with several instances. When Amazon EC2 decides whether to let traffic reach an instance, it evaluates all the rules from all the security groups associated with that instance. If you did not specify a security group at launch, Amazon EC2 used the default security group for the VPC (your private network inside the cloud).&lt;/p&gt;

&lt;p&gt;That gives you a short investigation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the instance's details in the EC2 console and list every security group attached to it.&lt;/li&gt;
&lt;li&gt;For each group, open the &lt;strong&gt;Inbound rules&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Look for a rule with protocol TCP, port 80 or 443, and a source that includes the address you are browsing from.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; if no group has such a rule, you have found the closed door. A common surprise is an instance running on the default group. In practice that group often has no rule for web traffic from the internet, because nobody added one.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv0yt9u05f88824mo2m82.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv0yt9u05f88824mo2m82.png" alt="A table of four checks, where to find each, and what a missing web rule looks like" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Every attached group counts, so check each group's inbound rules for ports 80 and 443&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Add the web server rules and watch the page load
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; let anyone on the internet reach your page, and nothing else.&lt;/p&gt;

&lt;p&gt;An instance set up as a web server needs security group rules that allow inbound HTTP and HTTPS access. The documented rules allow TCP port 80 (HTTP) and TCP port 443 (HTTPS) from 0.0.0.0/0, which means any IPv4 address. If your VPC is enabled for IPv6, you can add matching rules for port 80 and port 443 from ::/0, meaning any IPv6 address. TCP has protocol number 6. You may see that number in rule listings.&lt;/p&gt;

&lt;p&gt;Add these rules to one of the groups attached to the instance. Do not add them to an unrelated group.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm32ky0e2v229aqwbbelq.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm32ky0e2v229aqwbbelq.png" alt="A table pairing ports 80 and 443 with IPv4 and IPv6 sources that allow web access from anywhere" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Four inbound rules open HTTP and HTTPS to any IPv4 or IPv6 address&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You do not need to restart anything. You can change a security group's rules at any time, and new or modified rules are applied automatically to every instance associated with the group.&lt;/p&gt;

&lt;p&gt;You also do not need a matching outbound rule for the replies. Security groups are &lt;strong&gt;stateful&lt;/strong&gt;: responses to allowed inbound traffic may flow out regardless of the outbound rules. The reverse also holds. If your instance sends a request, the response may flow back in regardless of the inbound rules.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi3y42151nc64yvswt4k4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi3y42151nc64yvswt4k4.png" alt="A request passes an inbound rule and its response returns without needing an outbound rule" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Statefulness lets the reply leave without an outbound rule once the request is allowed in&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; reload the browser tab and the page should appear. If it still times out, a sensible next check is whether the web server is listening on the port you opened. A rule for 443 does nothing if the server only serves on 80.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Narrow SSH to your own address
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; keep your administrative access and close it to everyone else.&lt;/p&gt;

&lt;p&gt;To connect to a Linux instance, the security group must have an inbound rule allowing SSH, which is TCP port 22. Windows instances use RDP on port 3389 instead. The documented source for that rule is not "anywhere". It is the public IPv4 address of your computer, or a range of addresses in your local network. If your VPC is enabled for IPv6 and your instance has an IPv6 address, you can enter an IPv6 address or range instead. Ranges are written in CIDR notation: an address followed by a slash and a prefix length, such as /32 for exactly one IPv4 address.&lt;/p&gt;

&lt;p&gt;The difference between the web rules and the SSH rule is the point of this step. Your page is meant for everyone. Your shell is meant for you. A sensible default is to treat any port 22 rule with source 0.0.0.0/0 as a mistake to correct, even when it was added "just to get in".&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the group's inbound rules, find the SSH rule on port 22.&lt;/li&gt;
&lt;li&gt;Change its source from 0.0.0.0/0 to your computer's public address with /32, or to your local network's range.&lt;/li&gt;
&lt;li&gt;Save. The change applies automatically to every instance associated with the group.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; SSH from your own machine still works, and SSH from any other network no longer reaches the instance. Keep in mind that your public address can change when you move between networks. In practice, if you suddenly cannot connect from a new location, the source in this rule is the first thing to update.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7urf9xdnq32ykkoe143.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7urf9xdnq32ykkoe143.png" alt="Web rules allow any address, while the SSH rule allows only your computer's address or local range" width="797" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Web ports face the whole internet while SSH faces only your own address&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Stop sharing keys by connecting through EC2 Instance Connect
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; control who may SSH in through permissions rather than by passing private key files around.&lt;/p&gt;

&lt;p&gt;Narrowing the source address limits &lt;em&gt;where&lt;/em&gt; SSH can come from. It does not decide &lt;em&gt;who&lt;/em&gt; holds the key. EC2 Instance Connect addresses that second question. It provides a secure way to connect to Linux instances over SSH. It uses identity and access management policies and principals to control SSH access, which removes the need to share and manage SSH keys. Every connection request made with EC2 Instance Connect is logged, so you can audit connection requests.&lt;/p&gt;

&lt;p&gt;Here is how a connection works. The EC2 Instance Connect API pushes an SSH public key to the instance metadata, where the key remains for 60 seconds. An access policy attached to your user is what authorises you to push that key. On the instance, the SSH daemon uses two settings, &lt;code&gt;AuthorizedKeysCommand&lt;/code&gt; and &lt;code&gt;AuthorizedKeysCommandUser&lt;/code&gt;, which are configured when EC2 Instance Connect is installed, to look up the public key in the instance metadata and authenticate you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Think of it as a visitor badge printed at reception:&lt;/em&gt; it is issued to a named person, it works only briefly, and the desk keeps a record. A long-lived key file is more like a house key that can be copied and lent without anyone knowing.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4u0nvzc04fnzxeztm7ja.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4u0nvzc04fnzxeztm7ja.png" alt="A policy-authorised user pushes a key to metadata, and the SSH daemon reads it there to authenticate the session" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Instance Connect pushes a short-lived key that the SSH daemon looks up to authenticate you&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can connect with EC2 Instance Connect from the Amazon EC2 console or from the SSH client of your choice. It costs nothing extra. As of 2026-10-14, it is available in all AWS Regions except the European Sovereign Cloud (Germany), and it is not supported in Local Zones.&lt;/p&gt;

&lt;p&gt;One point is easy to miss. Instance Connect still connects over SSH, so the port 22 rule from Step 3 still matters. Instance Connect decides who is allowed, and the security group decides from which address. In practice you want both controls in place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you should see:&lt;/strong&gt; a shell session opens without you having copied a private key onto your machine. Each attempt is recorded in the audit log.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Clean up what you opened
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; leave nothing exposed that you no longer need.&lt;/p&gt;

&lt;p&gt;Security is a shared responsibility. Security groups are one tool, and you have to configure them to meet your own needs. That responsibility includes removing things as well as adding them. Rules can be modified at any time, you can change an instance's security groups after launch, and you can delete a security group.&lt;/p&gt;

&lt;p&gt;A sensible teardown order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remove any temporary rule you added while debugging, especially an SSH rule open to 0.0.0.0/0.&lt;/li&gt;
&lt;li&gt;If you are finished with the instance, remove it before deleting groups, so no group is still associated with something running.&lt;/li&gt;
&lt;li&gt;Delete any security group you created only for this exercise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Security groups carry no additional charge. Cost is therefore no reason to delete them. The reason is exposure: a forgotten wide-open group can later be attached to a new instance by mistake.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj0l6rmhr7tj7ucpq4k46.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj0l6rmhr7tj7ucpq4k46.png" alt="Three cleanup steps in order: remove the open SSH rule, remove the instance, delete the exercise groups" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Teardown removes risky rules first, then the instance, then the groups made for the exercise&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When the security group is not the whole story
&lt;/h2&gt;

&lt;p&gt;Security groups are not the only possible filter. If your requirements go beyond what security groups provide, you can run your own firewall on the instance as well. If you or a setup script has done that, a correct security group can still sit in front of a host firewall that blocks port 80. Also, if the instance sits behind a load balancer, the load balancer's own security group must allow communication with the instances. In that design, the browser's traffic meets the load balancer's rules first.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;A page that times out on a fresh instance is most often a missing inbound rule. Check every security group attached to the instance, because all of their rules are evaluated together.&lt;/li&gt;
&lt;li&gt;Web traffic needs inbound TCP 80 and 443 from 0.0.0.0/0, plus ::/0 when the VPC uses IPv6. Rule changes apply at once, and statefulness lets replies out without an outbound rule.&lt;/li&gt;
&lt;li&gt;SSH on port 22 should come from your own public address or local range, never from everywhere.&lt;/li&gt;
&lt;li&gt;EC2 Instance Connect replaces shared keys with policy-controlled, short-lived keys and logged connection requests, but it still needs the port 22 rule.&lt;/li&gt;
&lt;li&gt;Clean up deliberately: remove temporary open rules first, then delete groups made only for the exercise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article does not settle everything a stuck page can involve. It does not cover a web server that is not listening, a firewall on the instance itself, or what happens to the instance's public address when you stop and start it, which the source pages used here do not describe. It also explains each change in terms of the rules to set, not the exact command-line syntax, which those pages do not give.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full article: &lt;a href="https://techeazyconsulting.com/how-to-find-the-closed-port-that-stops-an-ec2-web-page-loading-and-lock-down-ssh" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/how-to-find-the-closed-port-that-stops-an-ec2-web-page-loading-and-lock-down-ssh&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Full chapter: &lt;a href="https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-04" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-04&lt;/a&gt;
&amp;lt;!-- cf-origin:end --&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>infrastructure</category>
      <category>networking</category>
      <category>security</category>
    </item>
    <item>
      <title>🔐 Use the AWS CLI Without Access Keys, and Prove a Policy Before You Attach It (Hands-on)</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Sun, 11 Oct 2026 05:13:28 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/use-the-aws-cli-without-access-keys-and-prove-a-policy-before-you-attach-it-hands-on-4ek3</link>
      <guid>https://dev.to/techeazy_consulting/use-the-aws-cli-without-access-keys-and-prove-a-policy-before-you-attach-it-hands-on-4ek3</guid>
      <description>&lt;h2&gt;
  
  
  🎤 The interview question
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do you use the AWS CLI without an access key, and how do you know a policy works before you attach it?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The strong answer is two things you have &lt;strong&gt;actually run&lt;/strong&gt;: sign the CLI in with &lt;code&gt;aws login&lt;/code&gt;, and prove the policy in the &lt;strong&gt;IAM policy simulator&lt;/strong&gt; first. 20 minutes. 👇&lt;/p&gt;

&lt;p&gt;👉 Flow: &lt;strong&gt;Sign in without a key → Write the policy → Prove it in the simulator → Store it, look, delete&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧰 Before you start
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;💻 &lt;strong&gt;AWS CLI v2, version 2.32.0 or later&lt;/strong&gt; (&lt;code&gt;aws login&lt;/code&gt; needs it). Check with &lt;code&gt;aws --version&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;👤 &lt;strong&gt;Signed in to the console&lt;/strong&gt; as your everyday admin IAM user (not root). It needs the &lt;code&gt;SignInLocalDevelopmentAccess&lt;/code&gt; managed policy or broader, e.g. &lt;code&gt;AdministratorAccess&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🔑 Permissions used: &lt;code&gt;iam:SimulateCustomPolicy&lt;/code&gt;, &lt;code&gt;iam:CreatePolicy&lt;/code&gt;, &lt;code&gt;iam:GetPolicyVersion&lt;/code&gt;, &lt;code&gt;iam:DeletePolicy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🌍 &lt;strong&gt;Region:&lt;/strong&gt; &lt;code&gt;ap-south-1&lt;/code&gt;, or your usual one.&lt;/li&gt;
&lt;li&gt;💵 &lt;strong&gt;Cost: $0.&lt;/strong&gt; IAM and STS are free, and the simulator sends no real request to any service. No Free plan credits used.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔐 Step 1: Sign the CLI in without a key
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; an access key works until someone deletes it; one pushed to GitHub is a stolen account. &lt;code&gt;aws login&lt;/code&gt; reuses your console sign-in and gives the CLI &lt;strong&gt;temporary&lt;/strong&gt; credentials (refreshed every 15 minutes, 12 hours max).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
aws login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At &lt;code&gt;AWS Region [us-east-1]:&lt;/code&gt; type &lt;code&gt;ap-south-1&lt;/code&gt;. In the browser, pick your user, then return.&lt;/p&gt;

&lt;p&gt;✅ Expected: &lt;code&gt;aws-cli/2.32.0&lt;/code&gt; or newer, then &lt;code&gt;Updated profile default to use arn:aws:...&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now ask "who am I?" (it needs no permissions, so run it first whenever something is denied):&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
aws configure list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Expected: an &lt;code&gt;Arn&lt;/code&gt; ending in your user name, and &lt;code&gt;login&lt;/code&gt; in the TYPE column.&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;If&lt;/strong&gt; &lt;code&gt;aws login&lt;/code&gt; is rejected as an unknown command → your CLI is older than 2.32.0. Update: &lt;code&gt;curl -fsSL https://awscli.amazonaws.com/v2/install.sh | bash&lt;/code&gt;. &lt;strong&gt;If&lt;/strong&gt; you see an old user or &lt;code&gt;ExpiredToken&lt;/code&gt; → an access key in &lt;code&gt;~/.aws/credentials&lt;/code&gt; wins. Delete it and log in again.&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Step 2: Write a read-only policy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; interviewers listen for "least privilege": &lt;strong&gt;list one bucket, read its objects, nothing else&lt;/strong&gt;. The bucket needn't exist yet.&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="nv"&gt;BUCKET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hoc-site-ar-4821
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/hoc-unit2 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/hoc-unit2
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hoc-read-policy.json &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
  "Version": "2012-10-17",
  "Statement": [
    {"Sid": "ListTheBucket", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BUCKET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"},
    {"Sid": "ReadItsObjects", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BUCKET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;/*"}
  ]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👀 Note the two ARNs: &lt;code&gt;ListBucket&lt;/code&gt; acts on the &lt;strong&gt;bucket&lt;/strong&gt;, &lt;code&gt;GetObject&lt;/code&gt; on the &lt;strong&gt;objects&lt;/strong&gt; (&lt;code&gt;/*&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Step 3: Prove it in the simulator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; the simulator answers "would this be allowed?" without touching anything or saving the policy. A helper makes each test one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sim&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; aws iam simulate-custom-policy &lt;span class="nt"&gt;--policy-input-list&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--action-names&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--resource-arns&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'EvaluationResults[0].EvalDecision'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

sim hoc-read-policy.json s3:ListBucket arn:aws:s3:::&lt;span class="nv"&gt;$BUCKET&lt;/span&gt;
sim hoc-read-policy.json s3:GetObject  arn:aws:s3:::&lt;span class="nv"&gt;$BUCKET&lt;/span&gt;/index.html
sim hoc-read-policy.json s3:PutObject  arn:aws:s3:::&lt;span class="nv"&gt;$BUCKET&lt;/span&gt;/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Expected: &lt;code&gt;allowed&lt;/code&gt;, &lt;code&gt;allowed&lt;/code&gt;, &lt;code&gt;implicitDeny&lt;/code&gt; (the only other answer is &lt;code&gt;explicitDeny&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;📚 Why &lt;code&gt;implicitDeny&lt;/code&gt;? The &lt;a href="https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-02" rel="noopener noreferrer"&gt;full chapter explains how AWS decides&lt;/a&gt;, with an eight-request test list for this policy.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧨 Break it on purpose
&lt;/h2&gt;

&lt;p&gt;Put &lt;code&gt;ListBucket&lt;/code&gt; on the &lt;strong&gt;object&lt;/strong&gt; ARN, a classic beginner bug:&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;sed&lt;/span&gt; &lt;span class="s2"&gt;"s#&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;arn:aws:s3:::&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BUCKET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}#&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;arn:aws:s3:::&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BUCKET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/*&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}#"&lt;/span&gt; hoc-read-policy.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; broken.json
sim broken.json s3:ListBucket arn:aws:s3:::&lt;span class="nv"&gt;$BUCKET&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Expected: &lt;code&gt;implicitDeny&lt;/code&gt;. Wrong resource ARN, so listing fails, and you caught it &lt;strong&gt;before&lt;/strong&gt; a real user did.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Step 4: Store it, look at it, delete it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; the clean-up habit. Created, never attached, deleted.&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="nv"&gt;POLICY_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws iam create-policy &lt;span class="nt"&gt;--policy-name&lt;/span&gt; hoc-read-site-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-document&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;hoc-read-policy.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nv"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;project,Value&lt;span class="o"&gt;=&lt;/span&gt;hands-on-cloud &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; Policy.Arn &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$POLICY_ARN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
aws iam get-policy-version &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$POLICY_ARN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--version-id&lt;/span&gt; v1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'PolicyVersion.Document.Statement[].Sid'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Expected: &lt;code&gt;arn:aws:iam::&amp;lt;your account ID&amp;gt;:policy/hoc-read-site-bucket&lt;/code&gt;, then &lt;code&gt;["ListTheBucket", "ReadItsObjects"]&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧹 Cleanup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws iam delete-policy &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$POLICY_ARN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/hoc-unit2/broken.json
aws &lt;span class="nb"&gt;logout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;code&gt;delete-policy&lt;/code&gt; prints nothing. After &lt;code&gt;aws logout&lt;/code&gt;, &lt;code&gt;get-caller-identity&lt;/code&gt; fails: no credentials left. 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Say it in the interview
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"I never create access keys for my own CLI: &lt;code&gt;aws login&lt;/code&gt; gives it temporary credentials that expire on their own. Before a policy goes anywhere, I run the requests that must be allowed and must be denied through the IAM policy simulator, and fix it until they match."&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 What you can now say
&lt;/h2&gt;

&lt;p&gt;✅ "My CLI signs in with &lt;code&gt;aws login&lt;/code&gt;, not a key"&lt;br&gt;
✅ "First command when denied: &lt;code&gt;aws sts get-caller-identity&lt;/code&gt;"&lt;br&gt;
✅ "&lt;code&gt;ListBucket&lt;/code&gt; needs the bucket ARN, &lt;code&gt;GetObject&lt;/code&gt; the object ARN"&lt;br&gt;
✅ "I prove a policy in the simulator before I attach it"&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Go deeper
&lt;/h2&gt;

&lt;p&gt;This is the hands-on cut of &lt;strong&gt;Session 2&lt;/strong&gt; of our free &lt;em&gt;Hands-on Cloud for Freshers&lt;/em&gt; course: the three rules AWS decides by, and the model answer.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-02" rel="noopener noreferrer"&gt;Read the full chapter on TechEazy Consulting&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🚀 Real projects and a real internship certificate get you hired. Start at &lt;a href="https://www.techeazyconsulting.com" rel="noopener noreferrer"&gt;TechEazy Consulting&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🛡️ New AWS Account? Stop Surprise Bills in 10 Minutes (Hands-on)</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Sun, 11 Oct 2026 04:28:20 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/new-aws-account-stop-surprise-bills-in-10-minutes-hands-on-2loc</link>
      <guid>https://dev.to/techeazy_consulting/new-aws-account-stop-surprise-bills-in-10-minutes-hands-on-2loc</guid>
      <description>&lt;h2&gt;
  
  
  🎤 The interview question
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"You just opened a new AWS account. How do you make sure a mistake can't quietly cost you money?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Freshers get asked this a lot. A good answer is three things you have &lt;strong&gt;actually done&lt;/strong&gt;: know your plan, set an alert, and keep everything in one Region with one tag. Let's do all three in about 10 minutes. 👇&lt;/p&gt;

&lt;p&gt;👉 Flow: &lt;strong&gt;Check plan → Budget alert → Free Tier usage → One Region + one tag&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧾 Step 1: Know which plan you're on
&lt;/h2&gt;

&lt;p&gt;Since July 2025, a new AWS account picks a &lt;strong&gt;Free plan&lt;/strong&gt; or a &lt;strong&gt;Paid plan&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💵 Both get &lt;strong&gt;USD $100&lt;/strong&gt; in credits at sign-up, and up to &lt;strong&gt;$100 more&lt;/strong&gt; for completing activities&lt;/li&gt;
&lt;li&gt;⏳ The Free plan ends after &lt;strong&gt;6 months&lt;/strong&gt; or when credits run out, whichever is first&lt;/li&gt;
&lt;li&gt;🔒 When it ends, the account &lt;strong&gt;closes&lt;/strong&gt;. You have 90 days to upgrade before your data is deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check yours: &lt;strong&gt;AWS Console → Billing and Cost Management → Home&lt;/strong&gt; (credit balance and plan are shown there).&lt;/p&gt;

&lt;p&gt;✅ Interview line: &lt;em&gt;"I know which plan I'm on and when it ends."&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔔 Step 2: Create a budget that emails you
&lt;/h2&gt;

&lt;p&gt;Set your account ID once:&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="nv"&gt;ACCOUNT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sts get-caller-identity &lt;span class="nt"&gt;--query&lt;/span&gt; Account &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;strong&gt;$1 monthly budget&lt;/strong&gt; that emails you at 80%:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws budgets create-budget &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--account-id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ACCOUNT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--budget&lt;/span&gt; &lt;span class="s1"&gt;'{"BudgetName":"freshers-1-usd","BudgetLimit":{"Amount":"1","Unit":"USD"},"TimeUnit":"MONTHLY","BudgetType":"COST"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--notifications-with-subscribers&lt;/span&gt; &lt;span class="s1"&gt;'[{"Notification":{"NotificationType":"ACTUAL","ComparisonOperator":"GREATER_THAN","Threshold":80,"ThresholdType":"PERCENTAGE"},"Subscribers":[{"SubscriptionType":"EMAIL","Address":"you@example.com"}]}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm it exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws budgets describe-budgets &lt;span class="nt"&gt;--account-id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ACCOUNT_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Budgets[].BudgetName'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Expected: &lt;code&gt;["freshers-1-usd"]&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Step 3: See your Free Tier usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws freetier get-free-tier-usage &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each item shows the service, the limit and how much you've used. 👀 Run it after every lab.&lt;/p&gt;

&lt;p&gt;💡 Also turn on &lt;strong&gt;Billing preferences → Receive AWS Free Tier alerts&lt;/strong&gt; in the console. That's your &lt;strong&gt;second&lt;/strong&gt; way to hear about spending.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌍 Step 4: One Region, one tag
&lt;/h2&gt;

&lt;p&gt;Pick one Region and stick to it, so nothing hides in a Region you never open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure &lt;span class="nb"&gt;set &lt;/span&gt;region ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tag everything you create in a lab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 create-tags &lt;span class="nt"&gt;--resources&lt;/span&gt; &amp;lt;instance-id&amp;gt; &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nv"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;project,Value&lt;span class="o"&gt;=&lt;/span&gt;freshers-lab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find everything with that tag before you log off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws resourcegroupstaggingapi get-resources &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--tag-filters&lt;/span&gt; &lt;span class="nv"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;project,Values&lt;span class="o"&gt;=&lt;/span&gt;freshers-lab &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'ResourceTagMappingList[].ResourceARN'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ An empty list &lt;code&gt;[]&lt;/code&gt; = nothing left running. 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  🧨 Break it on purpose
&lt;/h2&gt;

&lt;p&gt;Set the budget to &lt;strong&gt;$0.01&lt;/strong&gt;, launch a &lt;code&gt;t2.micro&lt;/code&gt; for an hour, and watch for the email. Then stop the instance. Now you &lt;em&gt;know&lt;/em&gt; your alert works.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 What you can now say in the interview
&lt;/h2&gt;

&lt;p&gt;✅ "I know my plan and when it ends"&lt;br&gt;
✅ "A budget emails me before I spend real money"&lt;br&gt;
✅ "I check Free Tier usage after every lab"&lt;br&gt;
✅ "I work in one Region and tag everything, so cleanup takes one command"&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Go deeper
&lt;/h2&gt;

&lt;p&gt;This is the hands-on cut of &lt;strong&gt;Session 1&lt;/strong&gt; of our free &lt;em&gt;Hands-on Cloud for Freshers&lt;/em&gt; course: the full chapter explains &lt;em&gt;why&lt;/em&gt; each step matters and what interviewers listen for.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://techeazyconsulting.com/courses/hands-on-cloud-for-freshers/session-01" rel="noopener noreferrer"&gt;Read the full chapter on TechEazy Consulting&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🚀 Real projects and a real internship certificate get you hired. Start at &lt;a href="https://www.techeazyconsulting.com" rel="noopener noreferrer"&gt;TechEazy Consulting&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>cloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to explain protecting the AWS root user and everyday admin access in an interview</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Sun, 11 Oct 2026 03:18:47 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/how-to-explain-protecting-the-aws-root-user-and-everyday-admin-access-in-an-interview-3pkh</link>
      <guid>https://dev.to/techeazy_consulting/how-to-explain-protecting-the-aws-root-user-and-everyday-admin-access-in-an-interview-3pkh</guid>
      <description>&lt;p&gt;The interviewer leans back and asks: "You've just created a new AWS account. What's the first thing you do about security?" Many freshers answer "enable MFA" and stop there. That answer is correct, but it is incomplete. A complete answer has two halves. First, lock the root user: give it a strong password and multi-factor authentication, create no access keys for it, and control who can recover it. Second, put it away: do everyday work through a separate administrative identity that uses temporary credentials. The rest of this article works through the questions you are likely to hear, answers each from current AWS IAM guidance (as of 2026-10-08), and ends with what to practise before you sit down.&lt;/p&gt;

&lt;h2&gt;
  
  
  The root user is the identity with complete access, so it is not for daily work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"What is the AWS account root user?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you first create an AWS account, it comes with a default set of credentials that have complete access to all AWS resources in the account, and this identity is called the AWS account root user. AWS strongly recommends that you don't use the root user unless you have a task that actually requires root user credentials. Instead, you create an administrative user for everyday tasks.&lt;/p&gt;

&lt;p&gt;Think of it as the master key to a building. You don't carry it on your keyring for opening your office each morning. You lock it in a safe and use a key cut for the doors you need.&lt;/p&gt;

&lt;p&gt;A good interview answer names both halves of the idea. The root user is powerful, so you protect it. It is also rarely needed, so you stop using it. Interviewers often listen for whether you mention the second half.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frifxxigti3pqvrsjq3u8.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frifxxigti3pqvrsjq3u8.png" alt="A new account's root user is locked and kept for root-only tasks, while an administrative user handles everyday tasks" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lock the root user, then route everyday work through an administrative identity&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Locking the root user means a strong password, MFA, and no access keys
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"How would you secure the root user's credentials?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start with the password. AWS recommends a password that is strong and unique, and a password manager with strong generation can help. AWS also enforces minimum rules. The password must be 8 to 128 characters long and include at least three of these types: uppercase letters, lowercase letters, numbers and symbols. It also must not match the account name or email address.&lt;/p&gt;

&lt;p&gt;Next, add multi-factor authentication (MFA), meaning a second proof of identity on top of the email address and password. All account types (standalone, management and member accounts) require MFA to be configured for their root user. If MFA is not already enabled, it must be registered within a grace period that begins at the first sign-in attempt to the console. You can register up to eight MFA devices of any mix of supported types, and AWS strongly recommends registering more than one for resilience.&lt;/p&gt;

&lt;p&gt;Supported types include FIDO-certified hardware security keys, hardware tokens that show a six-digit time-based one-time password (TOTP), and virtual authenticator apps on a phone. Setting up a virtual device is done while signed in as the root user. You scan a QR code, then enter two consecutive codes from the app. That setup step also explains why spare devices matter. If you lose the only phone holding the virtual device and have no other device or recovery path, you cannot sign in, and you have to contact customer service to remove MFA from the account.&lt;/p&gt;

&lt;p&gt;Then comes the point many freshers miss: &lt;strong&gt;don't create access keys for the root user&lt;/strong&gt;. Access keys let you run commands in the command line interface or call the API from a software development kit (SDK). Root access keys would carry full access to every service and resource, including billing information. Root-only tasks are rare, so AWS recommends doing them by signing in to the console. If programmatic access is genuinely needed, the &lt;code&gt;aws login&lt;/code&gt; command with root credentials provides temporary, automatically rotated credentials instead of long-term keys.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh0j99tv9iuvk9domfb5t.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh0j99tv9iuvk9domfb5t.png" alt="Table pairing four root user controls with the risk each one prevents" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Each root user control and the risk it closes&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it away means everyday work runs through temporary credentials
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"If not the root user, then what do you use day to day?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You create an administrative user, and from it you create other identities for the people who need access. AWS strongly recommends that users authenticate with temporary credentials. The right tool depends on how the accounts are set up.&lt;/p&gt;

&lt;p&gt;For a single, standalone account, AWS points to IAM roles. A role has no standard long-term credential such as a password or access key. When you assume a role, you receive temporary security credentials for that session. For several accounts managed together through AWS Organizations, AWS points to IAM Identity Center workforce users. These let you manage users and their permissions centrally across accounts, either in Identity Center itself or through an external identity provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"So what's wrong with IAM users?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IAM users have long-term credentials such as passwords and access keys. Current guidance is that human users should use federation (signing in through an identity provider) to get temporary credentials. IAM users should be kept for specific cases that federated users cannot handle. Two such cases are emergency access and workloads that cannot use IAM roles.&lt;/p&gt;

&lt;p&gt;If you do create an IAM user, the guidance still applies. Create only the credentials the user needs, so a console-only user gets no access keys. Manage permissions through groups rather than attaching them one user at a time. You can also set a permissions boundary, which caps the maximum permissions a user can have without granting any.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh9yk8zftsk0msgxi6beb.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh9yk8zftsk0msgxi6beb.png" alt="Comparison of IAM roles, Identity Center users and IAM users by credential type and when to use each" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Roles and Identity Center hand out temporary credentials; IAM users carry long-term ones&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A useful rule for interviews, offered here as judgment rather than as AWS wording: choose a role or a federated identity by default, and choose an IAM user only when you can name the specific reason a temporary credential won't work.&lt;/p&gt;

&lt;h2&gt;
  
  
  No single person should hold every key to the root user
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Who should have access to the root user's credentials?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Only people with a strict business need. Don't share the root password, MFA, access keys or signing certificates with anyone else. AWS goes further and suggests multi-person approval. One group of administrators holds the password, another group holds the MFA, and one member from each group must come together to sign in as root.&lt;/p&gt;

&lt;p&gt;Think of it as a bank vault that needs two keyholders to open. Neither can open it alone, so a single compromised or careless person is not enough.&lt;/p&gt;

&lt;p&gt;Storage needs the same care. Don't store the root password in a tool that runs on AWS services inside the same account that password protects. If you lose the password, you also lose access to the tool holding it. Access to the password or to wherever it is stored should be logged and monitored.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What email address should the root user have?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use a business-managed email address that forwards messages to a group of people. That way, if AWS needs to reach the owner, a reply doesn't wait on one person who is away, ill or has left. That address should not be used for anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recovery channels need the same protection as the password
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"How would someone recover root access, and how do you protect that path?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a strong follow-up, because recovery is a back door. You need access to the root email inbox to reset a lost password. If one MFA device fails, you can sign in with another device registered to the root user. If you have lost every MFA device, recovery requires both the email address and the phone number used to register the account, and both must be current and reachable.&lt;/p&gt;

&lt;p&gt;The email inbox and the phone number are both verification channels for recovering the root password. For that reason, no one person should control both. AWS recommends two groups: one with access to the primary email address and another with access to the primary phone number.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6j7v5ttcteajrzho19xb.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6j7v5ttcteajrzho19xb.png" alt="Group one holds the root email inbox, group two holds the phone number, and recovery needs both" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Splitting recovery channels between two groups means no one person can recover root alone&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  With many accounts, member root credentials can be removed altogether
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"How does this change when a company runs many AWS accounts?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With AWS Organizations, every account has its own root user to secure. The account that creates the organization is the management account, and its root user must have MFA registered. The other accounts are member accounts.&lt;/p&gt;

&lt;p&gt;For member accounts there are two strategies. The first is to centralize root access. You remove the member account's root password, access keys and signing certificates, and deactivate and delete its MFA, so the member account can no longer sign in as root or recover its root password. The second is to keep those root credentials and secure them with MFA. AWS recommends removing root credentials from member accounts. Where member root credentials stay enabled, a service control policy (an organization-wide permission guardrail) can deny all root actions except certain root-only ones.&lt;/p&gt;

&lt;p&gt;Compliance tools can give a misleading signal here. MFA-related checks report "noncompliant" when root credentials have been removed, because there is no MFA left to find. After removal, those member accounts are evaluated as "not applicable". Mentioning this nuance tends to show real understanding rather than memorised rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root sign-in should raise an alert that someone knows how to answer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"How would you know if someone used the root user?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWS recommends monitoring, alerting and reporting on root user sign-in and usage, including alerts that announce a root sign-in. The account's logging service records root sign-ins and privileged root sessions as separate events. Event rules can detect root credential use and notify a security administrator. Configuration and posture-checking services can flag a root user without MFA or with access keys.&lt;/p&gt;

&lt;p&gt;An alert is only useful if someone acts on it. AWS says to have procedures so that whoever receives a root alert knows how to confirm the access was expected. They should also know how to escalate if they suspect an incident.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff8oj2bcee7mi82v4v3df.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff8oj2bcee7mi82v4v3df.png" alt="Root sign-in triggers a logged event and a notification, which the administrator validates or escalates" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A root sign-in becomes an alert, then a check against expected work, then escalation if unexpected&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What to practise before the interview
&lt;/h2&gt;

&lt;p&gt;Answers stick when you have done the steps yourself. In a practice account, the following exercises are a sensible preparation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a strong root password, then register two MFA devices, so you can explain why a single device is a risk.&lt;/li&gt;
&lt;li&gt;Check that the root user has no access keys, and be ready to say why there should be none.&lt;/li&gt;
&lt;li&gt;Create an administrative identity and sign in through it for everything else. In a standalone account, try assuming a role and notice that the session credentials are temporary.&lt;/li&gt;
&lt;li&gt;Say aloud, in one breath, who holds the root password, who holds its MFA, who holds the recovery email and who holds the recovery phone.&lt;/li&gt;
&lt;li&gt;Sketch the alert path for a root sign-in, ending with what the person who receives the alert should do.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;The root user has complete access to every resource in the account, so you lock it with a strong password and MFA on more than one device, and you never create root access keys.&lt;/li&gt;
&lt;li&gt;After locking it, you put it away: everyday work goes through an administrative identity, and people sign in with temporary credentials from roles or IAM Identity Center rather than long-term IAM user credentials.&lt;/li&gt;
&lt;li&gt;No single person should hold both the root password and its MFA, or both recovery channels (the email inbox and the phone number).&lt;/li&gt;
&lt;li&gt;In an organization, removing member accounts' root credentials is the recommended approach, and root sign-ins everywhere should trigger alerts backed by a response procedure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article settles what to say about root-user protection and the shape of everyday administrative access. It does not cover how to design the permission policies that the everyday administrator and other users receive, and it does not list the specific tasks that still require root credentials. Those are the natural next questions an interviewer may ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full article: &lt;a href="https://techeazyconsulting.com/how-to-explain-protecting-the-aws-root-user-and-everyday-admin-access-in-an-interview" rel="noopener noreferrer"&gt;https://techeazyconsulting.com/how-to-explain-protecting-the-aws-root-user-and-everyday-admin-access-in-an-interview&lt;/a&gt;
&amp;lt;!-- cf-origin:end --&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>career</category>
      <category>interview</category>
      <category>security</category>
    </item>
    <item>
      <title>How AI Agents Use Tools, Memory, and MCP to Get Work Done</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Wed, 07 Oct 2026 01:59:29 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/how-ai-agents-use-tools-memory-and-mcp-to-get-work-done-82p</link>
      <guid>https://dev.to/techeazy_consulting/how-ai-agents-use-tools-memory-and-mcp-to-get-work-done-82p</guid>
      <description>&lt;p&gt;A customer asks where a shipment is, whether it will arrive late, and what should happen if it does. A language model alone can produce a polished reply, but it cannot know the current location, inspect live conditions, or change a booking. An AI agent can do those things because it works in a loop: it chooses an action, asks a runtime to execute it, observes the result, and decides what comes next. Tools provide the actions, memory carries useful context, the Model Context Protocol standardises connections to external systems, and orchestration keeps the whole process moving toward a clear stopping point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent loop turns an answer into a process
&lt;/h2&gt;

&lt;p&gt;A single model call takes an input and produces an output. Even if that output is accurate and detailed, the model has no opportunity to act, inspect what happened, and revise its decision.&lt;/p&gt;

&lt;p&gt;An agent adds that opportunity. Given a goal, it decides whether it has enough information to answer or needs an action first. After an action returns a result, the agent treats that result as new context. It can then call another tool, change direction, or finish.&lt;/p&gt;

&lt;p&gt;Consider an agent handling a shipment question. It may first request the tracking record. If the record reports a disruption, the agent may inspect a schedule and current operating conditions before forming an answer. Each observation affects the next decision.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7nayp01ynr9hm9di3p3e.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7nayp01ynr9hm9di3p3e.png" alt="A goal enters a repeating decide, act, and observe loop that ends with a final answer." width="798" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An agent repeats decisions and actions until it has enough evidence to answer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of it as a doctor ordering a laboratory test. The doctor decides which test is needed, but the laboratory performs it. The result returns to the doctor, who interprets it and decides whether more investigation is necessary. The useful capability comes from the entire loop, not from either participant acting alone.&lt;/p&gt;

&lt;p&gt;This distinction gives engineers a practical test: can an external result come back and change what the system does? If not, the application is using a model, but it is not operating as an agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools let the agent act without making the model the executor
&lt;/h2&gt;

&lt;p&gt;A tool is an external function, API, or data source made available to the agent. It might retrieve a record, search a document store, calculate a value, update a ticket, or submit a booking.&lt;/p&gt;

&lt;p&gt;The model does not execute the tool. It identifies the appropriate tool and produces the arguments for a requested call. The surrounding runtime validates and executes that request, then places the result into the model’s context. The model interprets the result and chooses the next step.&lt;/p&gt;

&lt;p&gt;That division of responsibility matters. Saying that “the model queried the database” hides the component that actually controls credentials, network access, input validation, timeouts, and returned data. Those responsibilities belong to the runtime and its integrations.&lt;/p&gt;

&lt;p&gt;For example, suppose an agent needs the stock level for a part. The model may request &lt;code&gt;get_stock&lt;/code&gt; with a part identifier. The runtime calls the inventory system and returns the current quantity. Only then does the model construct its answer. Without the tool, it could generate a plausible quantity; with the tool, it can reason from the retrieved one.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F435bxbdfukey31t0xp1i.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F435bxbdfukey31t0xp1i.png" alt="The model asks the runtime to call an external system, then interprets the returned result." width="799" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The model requests an action; the runtime executes it and returns the result.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tools are especially valuable when facts can change after a model was trained. Account state, inventory, schedules, policies, and reservations all require access to current systems. Tools also turn advice into action: instead of describing how to make a booking, an agent can request the booking and inspect its confirmation.&lt;/p&gt;

&lt;p&gt;Access should still be bounded. A tool-enabled agent can only request actions exposed by its runtime, and the runtime remains responsible for deciding what is permitted. The agent loop provides flexibility; it does not remove the need for controlled execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP standardises the connection to external systems
&lt;/h2&gt;

&lt;p&gt;Connecting one application to one tool can be straightforward. Connecting many AI applications to many databases, file stores, internal APIs, and other systems creates a larger integration problem. If every application needs a custom connector for every system, the work grows with every new pair.&lt;/p&gt;

&lt;p&gt;The Model Context Protocol, or MCP, is an open protocol that standardises how an AI application connects models to external tools and data sources. Instead of teaching every application the private interface of every external system, each side implements a shared interface.&lt;/p&gt;

&lt;p&gt;For an illustrative example, three applications connected independently to four systems require twelve bespoke integrations. With a common protocol, the three applications and four systems each implement their side of the interface, producing seven implementations. Adding another system then requires one new implementation rather than one connector for every application.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9mz1d5tsfw0dlysz1534.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9mz1d5tsfw0dlysz1534.png" alt="Bespoke connections need a connector per pair, while MCP provides a shared interface." width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A shared protocol replaces many application-to-system connectors with one interface.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of MCP as a common electrical socket. Appliance makers build for the socket rather than negotiating a different connection with every building. The socket does not generate electricity or perform the appliance’s job; it only defines how the connection works.&lt;/p&gt;

&lt;p&gt;Likewise, MCP does not replace tools. The database still answers queries, and the booking API still creates bookings. MCP standardises how those capabilities are presented and used. Tools can also work without MCP, particularly when a system has only a small number of stable integrations.&lt;/p&gt;

&lt;p&gt;The endpoints provide the simplest boundary test: MCP connects an agent to an external system. It does not define how several agents communicate with one another. Agent-to-agent exchange requires communication patterns such as direct messages, shared state, broadcasts, or queues.&lt;/p&gt;

&lt;p&gt;MCP is also neither a model nor a hosted service. It is a protocol that compatible applications and systems can speak. Treating it as a product obscures the integration problem it actually solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory carries selected context, not the entire past
&lt;/h2&gt;

&lt;p&gt;A model is stateless between calls. If an agent needs earlier information, the application must supply that information again. Memory management is the deliberate choice of what to carry forward, how long to keep it, and what to discard.&lt;/p&gt;

&lt;p&gt;Working memory contains material needed for the current task: recent turns, the active goal, intermediate decisions, and the latest tool result. Once the task ends, that state usually loses its value.&lt;/p&gt;

&lt;p&gt;Persistent memory holds facts that must survive across separate sessions. Examples include a customer’s communication preference or a durable outcome from an earlier case. This information is stored outside the model and retrieved when it becomes relevant.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frao9777h1c2172638fao.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frao9777h1c2172638fao.png" alt="Information is routed by whether it must survive, then discarded or retrieved selectively." width="800" height="936"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Task-local context stays in working memory; durable facts enter persistent memory.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of working memory as a desk and persistent memory as a filing cabinet. The desk holds the papers required for the current job. The cabinet holds durable records, but you retrieve only the folder relevant to the work in front of you.&lt;/p&gt;

&lt;p&gt;Keeping everything is not a safe default. Re-supplying an entire conversation makes every call carry material that may no longer matter. Useful evidence can become harder to find among old details, while unnecessary retention increases cost and risk.&lt;/p&gt;

&lt;p&gt;A strong memory policy therefore includes forgetting. A tool result needed for the next decision belongs in working memory. A lasting preference may justify persistent storage. A one-use verification code should be discarded. A long conversation is often better represented by a selected summary than by a verbatim transcript.&lt;/p&gt;

&lt;p&gt;The design question is not “How can the agent remember more?” It is “What must survive, and what must not?”&lt;/p&gt;

&lt;h2&gt;
  
  
  Orchestration coordinates tools, memory, and specialist agents
&lt;/h2&gt;

&lt;p&gt;Workflow orchestration owns the progress of an agentic task. It sequences steps, routes work, handles failures and retries, and decides when the task is finished. Without that control, an agent may have useful tools and memory yet still repeat actions, stall after an error, or stop before reaching the goal.&lt;/p&gt;

&lt;p&gt;A deterministic workflow has developer-defined steps and branches. It is predictable, testable, and auditable, making it suitable when the permitted path must remain stable. A model-driven workflow lets the model choose each next step. It can adapt to unexpected situations, but its path may vary between runs.&lt;/p&gt;

&lt;p&gt;For example, a routine record lookup can follow a deterministic sequence: validate the identifier, call the record tool, format the response, and stop. An investigation involving incomplete evidence may benefit from model-driven choices about which source to inspect next. The appropriate design depends on whether variation is useful or a defect.&lt;/p&gt;

&lt;p&gt;Some tasks also justify multiple agents. The key test is whether the task spans genuinely distinct specialisms, not whether it merely contains many steps.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkjywu1lptf1g7tgji7vi.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkjywu1lptf1g7tgji7vi.png" alt="A task routes to one agent or coordinated specialists before orchestration completes it." width="800" height="887"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bounded work stays with one agent; distinct specialisms justify coordinated agents.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A supervisor pattern uses a lead agent to divide work among specialists and assemble their findings. A sequential pattern passes each agent’s output to the next stage. A parallel pattern lets independent specialists work separately before their results are merged. A hierarchical pattern adds layers of supervision for deeper decomposition.&lt;/p&gt;

&lt;p&gt;These structures do not determine how information travels. A supervisor can contact specialists directly or coordinate through shared state. Agents may broadcast an update to several peers or use a message queue when producers and consumers must remain decoupled. The system pattern is the org chart; the communication pattern is how the memos move.&lt;/p&gt;

&lt;p&gt;Multiple agents add model calls, latency, failure modes, and debugging surface. A shipment lookup that only needs a tracking tool should remain with one agent. A disruption analysis requiring separate pricing, customs, and capacity expertise may justify a supervisor and specialists. Good orchestration can route those two cases down different paths instead of forcing every request through the larger system.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;An agent is defined by its loop: decide, act, observe, and decide again.&lt;/li&gt;
&lt;li&gt;The model requests tool calls; the surrounding runtime executes them.&lt;/li&gt;
&lt;li&gt;Tools give agents access to current information and real actions.&lt;/li&gt;
&lt;li&gt;MCP standardises agent-to-system connections but does not replace tools.&lt;/li&gt;
&lt;li&gt;MCP does not govern communication between agents.&lt;/li&gt;
&lt;li&gt;Working memory serves the current task; persistent memory stores selected durable facts.&lt;/li&gt;
&lt;li&gt;Orchestration controls sequencing, routing, failure handling, and completion.&lt;/li&gt;
&lt;li&gt;One agent with good tools is the default; multiple agents need distinct specialisms to justify their cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concepts explain how an agentic application gets work done, but they do not by themselves choose the right permissions, retention policy, tools, or workflow for a particular system. Those decisions depend on the task’s risks, required evidence, tolerance for variable behavior, and the consequences of an incorrect action.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/kMnqfnpvbnI" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>aifc01</category>
    </item>
    <item>
      <title>Scaling Spring Boot with Auto Scaling Group (ASG) + Elastic Load Balancer (ELB)</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Fri, 03 Oct 2025 06:24:09 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/scaling-spring-boot-with-auto-scaling-group-asg-elastic-load-balancer-elb-1293</link>
      <guid>https://dev.to/techeazy_consulting/scaling-spring-boot-with-auto-scaling-group-asg-elastic-load-balancer-elb-1293</guid>
      <description>&lt;p&gt;Deploying a Spring Boot app on &lt;strong&gt;multiple EC2 instances&lt;/strong&gt; with an &lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt; works great ✅&lt;br&gt;
But what happens when traffic spikes? Or if one EC2 instance crashes?&lt;/p&gt;

&lt;p&gt;👉 That’s where &lt;strong&gt;Auto Scaling Groups (ASG)&lt;/strong&gt; step in.&lt;/p&gt;

&lt;p&gt;By the end of this guide, you’ll know how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an &lt;strong&gt;AMI&lt;/strong&gt; of your Spring Boot app&lt;/li&gt;
&lt;li&gt;Build a &lt;strong&gt;Launch Template&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure an &lt;strong&gt;Auto Scaling Group (ASG)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Integrate it with your &lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Auto-scale your application 🚀&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Flow: &lt;strong&gt;Browser → ELB → ASG → EC2 Instances running Spring Boot&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  🔑 Pre-requisite
&lt;/h2&gt;

&lt;p&gt;From the &lt;strong&gt;previous blog&lt;/strong&gt;, you should already have:&lt;/p&gt;

&lt;p&gt;✅ 2 EC2 instances with Spring Boot JAR deployed on &lt;strong&gt;port 8080&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ Application Load Balancer (ALB) setup with a Target Group  &lt;/p&gt;


&lt;h2&gt;
  
  
  📦 Step 1: Create an AMI (Golden Image)
&lt;/h2&gt;

&lt;p&gt;We’ll use one existing EC2 as a &lt;strong&gt;base image (AMI)&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;EC2 Dashboard → Instances&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select an EC2 instance where your Spring Boot app is running&lt;/li&gt;
&lt;li&gt;From &lt;strong&gt;Actions → Image and Templates → Create Image&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name it: &lt;code&gt;springboot-ami&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create AMI&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⏳ Wait 8–10 minutes. This AMI will be the &lt;strong&gt;blueprint&lt;/strong&gt; for new EC2s in the ASG.&lt;/p&gt;


&lt;h2&gt;
  
  
  📝 Step 2: Create a Launch Template
&lt;/h2&gt;

&lt;p&gt;Launch Template = Recipe to spin up new EC2s.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;strong&gt;EC2 → Auto Scaling Groups → Create Auto Scaling Group&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;strong&gt;Launch Template&lt;/strong&gt;, click &lt;strong&gt;Create new launch template&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill details:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;springboot-template&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;AMI: Select &lt;strong&gt;My AMIs → springboot-ami&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Instance type: &lt;code&gt;t3.micro&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Key Pair: Same as before&lt;/li&gt;
&lt;li&gt;Security Group: Must allow &lt;strong&gt;22 (SSH), 80 (HTTP), 8080 (Spring Boot)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;strong&gt;User Data&lt;/strong&gt; (to auto-start the app):
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/ubuntu
&lt;span class="nb"&gt;sudo nohup &lt;/span&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; app.jar &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; app.log 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Create Launch Template&lt;/strong&gt; ✅&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  ⚙️ Step 3: Create Auto Scaling Group (ASG)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Back to &lt;strong&gt;Auto Scaling Group creation&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;springboot-asg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;Launch Template&lt;/strong&gt; you just created&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  🌐 Step 4: Configure Network Settings
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;VPC → Default VPC&lt;/li&gt;
&lt;li&gt;Subnets → Select available ones (where ALB exists)&lt;/li&gt;
&lt;li&gt;Leave defaults → &lt;strong&gt;Next&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🔗 Step 5: Integrate with Load Balancer
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;On &lt;strong&gt;Load Balancer settings&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Attach to &lt;strong&gt;existing Load Balancer&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select your &lt;strong&gt;Spring Boot Target Group (8080)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;ALB health checks&lt;/strong&gt; for reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  📊 Step 6: Set Group Size &amp;amp; Scaling Policy
&lt;/h2&gt;

&lt;p&gt;Define scaling behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desired capacity&lt;/strong&gt; → &lt;code&gt;2&lt;/code&gt; (start with 2 instances)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimum capacity&lt;/strong&gt; → &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maximum capacity&lt;/strong&gt; → &lt;code&gt;3&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add a scaling policy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Policy type → &lt;strong&gt;Target tracking&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Metric → &lt;strong&gt;ALB Request Count per Target&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Target Group → &lt;code&gt;springboot-tg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Target Value → &lt;code&gt;50&lt;/code&gt; (scale out if &amp;gt;50 requests per instance)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  ✅ Step 7: Review &amp;amp; Create
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Double-check everything&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Auto Scaling Group&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your ASG is now active 🎉&lt;/p&gt;


&lt;h2&gt;
  
  
  🔍 Step 8: Verify Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;EC2 → Instances&lt;/strong&gt; → You’ll see new instances launched by ASG&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;ELB → Target Group → Targets&lt;/strong&gt; → Should show healthy instances&lt;/li&gt;
&lt;li&gt;Try &lt;strong&gt;terminating one instance manually&lt;/strong&gt; → ASG will auto-recreate it!&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🧪 Step 9: Load Test Your Setup
&lt;/h2&gt;

&lt;p&gt;To simulate traffic for 5 mins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ab &lt;span class="nt"&gt;-n&lt;/span&gt; 1000 &lt;span class="nt"&gt;-c&lt;/span&gt; 50 http://&amp;lt;ALB_DNS_NAME&amp;gt;/api/adapt/welcome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Using ApacheBench or any load testing tool)&lt;/p&gt;

&lt;p&gt;🎯 ASG will launch new EC2s automatically if traffic increases.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Final Result
&lt;/h2&gt;

&lt;p&gt;You’ve successfully:&lt;/p&gt;

&lt;p&gt;✅ Created an AMI for your Spring Boot app&lt;br&gt;&lt;br&gt;
✅ Configured a Launch Template&lt;br&gt;&lt;br&gt;
✅ Built an Auto Scaling Group (ASG)&lt;br&gt;&lt;br&gt;
✅ Integrated ASG with your Load Balancer&lt;br&gt;&lt;br&gt;
✅ Enabled &lt;strong&gt;self-healing + scaling&lt;/strong&gt; 🚀  &lt;/p&gt;

&lt;p&gt;Now your app can handle failures and traffic surges without manual effort 💪&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Next Steps 🚀
&lt;/h2&gt;

&lt;p&gt;Be interview-ready in the era of &lt;strong&gt;AI &amp;amp; Cloud&lt;/strong&gt; — start your &lt;strong&gt;DevOps journey&lt;/strong&gt; today!  &lt;/p&gt;

&lt;p&gt;💡 YouTube won’t get you a job. Real projects + real internship certificate will.&lt;br&gt;&lt;br&gt;
🔥 AI is reshaping jobs. Don’t watch it happen, be part of it with &lt;strong&gt;DevOps &amp;amp; Cloud skills&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
🎯 ₹2000/month today = Dream job tomorrow. Secure your spot now.&lt;br&gt;&lt;br&gt;
⏳ Every month you wait, &lt;strong&gt;Cloud + AI jobs&lt;/strong&gt; are being filled. Don’t miss out!&lt;br&gt;&lt;br&gt;
🌐 &lt;strong&gt;DevOps + AWS + AI = The skillset every recruiter is hunting for in 2025.&lt;/strong&gt;    &lt;/p&gt;

&lt;p&gt;👉 Register now at &lt;a href="https://www.techeazyconsulting.com" rel="noopener noreferrer"&gt;TechEazy Consulting&lt;/a&gt;&lt;/p&gt;




</description>
      <category>aws</category>
      <category>asg</category>
      <category>elb</category>
      <category>ai</category>
    </item>
    <item>
      <title>Deploy a Spring Boot App on AWS EC2 with Load Balancer (Step-by-Step Guide)</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Sat, 27 Sep 2025 05:10:41 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/deploy-a-spring-boot-app-on-aws-ec2-with-load-balancer-step-by-step-guide-47pe</link>
      <guid>https://dev.to/techeazy_consulting/deploy-a-spring-boot-app-on-aws-ec2-with-load-balancer-step-by-step-guide-47pe</guid>
      <description>&lt;h2&gt;
  
  
  🌍 Introduction
&lt;/h2&gt;

&lt;p&gt;Deploying your application manually on AWS can be time-consuming and error-prone. You might face:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic distributed unevenly across instances ❌&lt;/li&gt;
&lt;li&gt;Manual setup of health checks and failover ❌&lt;/li&gt;
&lt;li&gt;Lack of scalability and high availability ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 That’s where &lt;strong&gt;EC2 + ELB (Elastic Load Balancer)&lt;/strong&gt; deployment shines.&lt;/p&gt;

&lt;p&gt;By the end, you’ll understand how to deploy a &lt;strong&gt;Spring Boot app&lt;/strong&gt; on &lt;strong&gt;multiple EC2 instances&lt;/strong&gt;, set up an &lt;strong&gt;Application Load Balancer&lt;/strong&gt;, and route traffic intelligently.&lt;/p&gt;

&lt;p&gt;👉 Flow: &lt;strong&gt;Browser → ELB → EC2 Instances running Spring Boot&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Step 1: Prepare Your Spring Boot App
&lt;/h2&gt;

&lt;p&gt;Before we touch AWS, package your Spring Boot project into a runnable &lt;code&gt;.jar&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn clean package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get something like &lt;code&gt;app.jar&lt;/code&gt; in the &lt;code&gt;target/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;✅ We assume the app runs on &lt;strong&gt;port 8080&lt;/strong&gt;&lt;br&gt;
✅ Requires &lt;strong&gt;Java&lt;/strong&gt; and &lt;strong&gt;Maven&lt;/strong&gt; installed locally&lt;br&gt;
✅ Target is &lt;code&gt;.jar&lt;/code&gt; deployment, not Docker&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We used the adaptive-ai-qms Spring Boot app as an example. But you can replace it with any web application and port according to app.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  ⚡ Step 2: Launch EC2 Instances
&lt;/h2&gt;

&lt;p&gt;Let’s spin up two EC2 instances for our Spring Boot app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;AWS Console → EC2 → Launch Instance&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;OS: &lt;strong&gt;Ubuntu Server 24.04 LTS&lt;/strong&gt; (Free Tier eligible)&lt;/li&gt;
&lt;li&gt;Instance type: &lt;strong&gt;t2.micro&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Key Pair: Create/choose one (for SSH access)&lt;/li&gt;
&lt;li&gt;Configure Security Group:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSH (22)&lt;/strong&gt; → Your IP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP (80)&lt;/strong&gt; → Anywhere&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom TCP (8080)&lt;/strong&gt; → Anywhere (for Spring Boot)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🎯 &lt;strong&gt;Launch two EC2 instances&lt;/strong&gt; with the same configuration.&lt;/p&gt;


&lt;h2&gt;
  
  
  📜 Step 3: Install Java &amp;amp; Deploy Spring Boot App
&lt;/h2&gt;

&lt;p&gt;SSH into both instances:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; your-key.pem ubuntu@&amp;lt;EC2_PUBLIC_IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Java:&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 &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-21-jdk &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upload your app using &lt;code&gt;scp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; your-key.pem app.jar ubuntu@&amp;lt;EC2_PUBLIC_IP&amp;gt;:/home/ubuntu/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the app in the background:&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 nohup &lt;/span&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; app.jar &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; app.log 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nohup&lt;/code&gt;: Keeps process running after logout&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;java -jar&lt;/code&gt;: Runs your Spring Boot app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;gt; app.log 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/code&gt;: Logs output and runs in background&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Now access your app via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;http://&amp;lt;EC2_PUBLIC_IP&amp;gt;:8080/api/adapt/welcome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat for the second EC2 instance.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Step 4: Create an Elastic Load Balancer (ALB)
&lt;/h2&gt;

&lt;p&gt;Now we’ll route traffic to both EC2 instances via a Load Balancer.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;EC2 → Load Balancers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Load Balancer → Application Load Balancer&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;springboot-alb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scheme: &lt;strong&gt;Internet-facing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;VPC: Use &lt;strong&gt;default VPC&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select AZs: Pick where your EC2s are running&lt;/li&gt;
&lt;li&gt;Security Group:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Create a new one: &lt;code&gt;springboot-sg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Inbound Rules: Allow &lt;strong&gt;HTTP (80)&lt;/strong&gt; and &lt;strong&gt;SSH (22)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Listener Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Protocol: &lt;strong&gt;HTTP&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Port: &lt;strong&gt;80&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create Target Group
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Type: &lt;strong&gt;Instances&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;springboot-tg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Protocol: &lt;strong&gt;HTTP&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Port: &lt;strong&gt;8080&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Health check path: &lt;code&gt;/actuator/health/readiness&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Register your two EC2 instances&lt;br&gt;
✅ Attach this Target Group to the Load Balancer&lt;br&gt;
✅ Click &lt;strong&gt;Create Load Balancer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;strong&gt;ALB is now live&lt;/strong&gt; and routing traffic.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧪 Step 5: Test Your Setup
&lt;/h2&gt;

&lt;p&gt;🎯 Go to &lt;strong&gt;Load Balancer → Description&lt;/strong&gt; tab&lt;br&gt;
📄 Copy the &lt;strong&gt;DNS name&lt;/strong&gt; (e.g., &lt;code&gt;springboot-alb-123456.ap-south-1.elb.amazonaws.com&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Visit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;http://&amp;lt;DNS_NAME&amp;gt;/api/adapt/welcome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome to Adaptation Controller - Techeazy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Confirms ELB is routing to healthy EC2 instances&lt;br&gt;
✅ Confirms Spring Boot app is working across both instances&lt;/p&gt;

&lt;p&gt;🛠 You can now explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Manual deployment&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating AMIs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Using Launch Templates with Auto Scaling&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Conclusion
&lt;/h2&gt;

&lt;p&gt;You’ve successfully:&lt;/p&gt;

&lt;p&gt;✅ Deployed a Spring Boot app on EC2&lt;br&gt;
✅ Set up a Load Balancer to route traffic&lt;br&gt;
✅ Configured health checks to ensure uptime&lt;br&gt;
✅ Created a production-ready architecture for web-scale apps&lt;/p&gt;

&lt;p&gt;👉 Next, pair this setup with &lt;strong&gt;Auto Scaling Groups&lt;/strong&gt; for &lt;strong&gt;true elasticity and high availability&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Next Steps
&lt;/h2&gt;

&lt;p&gt;🚀 Be interview-ready in the era of AI &amp;amp; Cloud — start your DevOps journey today!&lt;br&gt;
💡 YouTube won’t get you a job. Real projects + real internship certificate will.&lt;br&gt;
🔥 AI is reshaping jobs. Don’t watch it happen, be part of it with DevOps &amp;amp; Cloud skills.&lt;br&gt;
⏳ Every month you wait, Cloud + AI jobs are being filled. Don’t miss out!&lt;br&gt;
🌐 DevOps + AWS + AI = The skillset every recruiter is hunting for in 2025.&lt;/p&gt;

&lt;p&gt;👉 Register now at &lt;a href="https://www.techeazyconsulting.com" rel="noopener noreferrer"&gt;TechEazy Consulting&lt;/a&gt;&lt;/p&gt;




</description>
      <category>springboot</category>
      <category>aws</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>AWS Auto Scaling Groups (ASG) – Beginner’s Guide</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Fri, 12 Sep 2025 06:16:10 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/aws-auto-scaling-groups-asg-beginners-guide-3ffa</link>
      <guid>https://dev.to/techeazy_consulting/aws-auto-scaling-groups-asg-beginners-guide-3ffa</guid>
      <description>&lt;h2&gt;
  
  
  🌍 Introduction
&lt;/h2&gt;

&lt;p&gt;When you run an application on AWS, &lt;strong&gt;manual server management&lt;/strong&gt; can be painful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sudden traffic spikes → servers run out of capacity ❌&lt;/li&gt;
&lt;li&gt;Low traffic hours → paying for unused servers ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 That’s where &lt;strong&gt;AWS Auto Scaling Groups (ASG)&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ASG&lt;/strong&gt; automatically adjusts the number of EC2 instances to match demand. This ensures:&lt;br&gt;&lt;br&gt;
✅ Cost efficiency&lt;br&gt;&lt;br&gt;
✅ High availability&lt;br&gt;&lt;br&gt;
✅ Scalability      &lt;/p&gt;

&lt;p&gt;By the end, you’ll understand:&lt;br&gt;
👉 &lt;strong&gt;Browser → ELB → Auto Scaling Group (dynamic scaling + health checks) → Healthy EC2 Instances&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Step 1: Understand Auto Scaling Group
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;Auto Scaling Group (ASG)&lt;/strong&gt; is a collection of EC2 instances that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scale &lt;strong&gt;out&lt;/strong&gt; (add instances) when demand increases&lt;/li&gt;
&lt;li&gt;Scale &lt;strong&gt;in&lt;/strong&gt; (remove instances) when demand drops&lt;/li&gt;
&lt;li&gt;Replace unhealthy instances automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you a &lt;strong&gt;self-healing, cost-optimized infrastructure&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Step 2: Learn Key ASG Terminologies
&lt;/h2&gt;

&lt;p&gt;Here are the &lt;strong&gt;basic terms&lt;/strong&gt; you’ll see when setting up ASG:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Launch Template/Config&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Blueprint defining AMI, instance type, key pairs, security groups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Desired Capacity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Number of instances you want running normally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Minimum Capacity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lowest number of instances allowed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maximum Capacity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Highest number of instances allowed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scaling Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rules to scale in/out (CPU &amp;gt; 70%, requests/sec, schedule-based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Health Check&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ensures only healthy instances remain in service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Termination Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Decides which instance to remove first when scaling in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Warm Pools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pre-initialized instances for faster scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Elastic Load Balancer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Commonly paired with ASG to distribute traffic among instances&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📜 Step 3: How ASG Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User&lt;/strong&gt; visits your app → request hits &lt;strong&gt;ELB&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ELB forwards traffic to instances in an &lt;strong&gt;Auto Scaling Group&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ASG monitors metrics (CPU, requests, custom metrics) via CloudWatch&lt;/li&gt;
&lt;li&gt;When demand increases → ASG launches new instances&lt;/li&gt;
&lt;li&gt;When demand decreases → ASG terminates extra instances&lt;/li&gt;
&lt;li&gt;If an instance becomes unhealthy → ASG replaces it automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 Flow: &lt;strong&gt;Browser → ELB → Auto Scaling Group → Healthy EC2 Instances&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Step 4: Benefits of ASG
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Scalability&lt;/strong&gt; – Adjusts capacity based on traffic automatically&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;High Availability&lt;/strong&gt; – Distributes instances across multiple AZs&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Cost Efficiency&lt;/strong&gt; – Pay only for the resources you actually need&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Self-Healing&lt;/strong&gt; – Replaces unhealthy instances automatically&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Flexible Policies&lt;/strong&gt; – Scale by schedule, metrics, or custom triggers    &lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Step 5: Real-World Example
&lt;/h2&gt;

&lt;p&gt;Imagine an &lt;strong&gt;E-commerce website&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You set &lt;strong&gt;min=2&lt;/strong&gt;, &lt;strong&gt;desired=3&lt;/strong&gt;, &lt;strong&gt;max=6&lt;/strong&gt; EC2 instances
&lt;/li&gt;
&lt;li&gt;Traffic spikes during a festival sale → ASG launches 3 more instances (total 6)
&lt;/li&gt;
&lt;li&gt;At midnight, traffic drops → ASG scales back to 3 instances
&lt;/li&gt;
&lt;li&gt;If one instance crashes → ASG replaces it automatically 🎉
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means your app stays &lt;strong&gt;responsive + cost-efficient&lt;/strong&gt; at all times.   &lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Conclusion
&lt;/h2&gt;

&lt;p&gt;With ASG, you get:&lt;/p&gt;

&lt;p&gt;✅ Right number of instances at the right time&lt;br&gt;&lt;br&gt;
✅ Lower costs during low demand&lt;br&gt;&lt;br&gt;
✅ High availability with automatic healing&lt;br&gt;&lt;br&gt;
✅ Seamless scaling with ELB integration       &lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;For web apps&lt;/strong&gt; – Combine ASG with ALB for best results&lt;br&gt;&lt;br&gt;
👉 &lt;strong&gt;For scheduled workloads&lt;/strong&gt; – Use scheduled scaling&lt;br&gt;&lt;br&gt;
👉 &lt;strong&gt;For unpredictable workloads&lt;/strong&gt; – Use dynamic scaling policies      &lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;recommended AWS setup&lt;/strong&gt; for building cost-efficient, highly available, production-grade applications 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Next Steps
&lt;/h2&gt;

&lt;p&gt;🚀 Be interview-ready in the era of AI &amp;amp; Cloud — start your DevOps journey today!&lt;br&gt;&lt;br&gt;
💡 YouTube won’t get you a job. Real projects + real internship certificate will.&lt;br&gt;&lt;br&gt;
🔥 AI is reshaping jobs. Don’t watch it happen, be part of it with DevOps &amp;amp; Cloud skills.&lt;br&gt;&lt;br&gt;
🎯 ₹2000/month today = Dream job tomorrow. Secure your spot now.&lt;br&gt;&lt;br&gt;
⏳ Every month you wait, Cloud + AI jobs are being filled. Don’t miss out!&lt;br&gt;&lt;br&gt;
🌐 DevOps + AWS + AI = The skillset every recruiter is hunting for in 2025.      &lt;/p&gt;

&lt;p&gt;👉 Register now at &lt;a href="https://www.techeazyconsulting.com" rel="noopener noreferrer"&gt;TechEazy Consulting&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Originally published at &lt;a href="https://blog.techeazyconsulting.com" rel="noopener noreferrer"&gt;https://blog.techeazyconsulting.com&lt;/a&gt; on September 12, 2025.
&lt;/h3&gt;




</description>
      <category>aws</category>
      <category>devops</category>
      <category>elb</category>
      <category>asg</category>
    </item>
    <item>
      <title>AWS Elastic Load Balancer (ELB) – Beginner’s Guide</title>
      <dc:creator>TechEazy Consulting</dc:creator>
      <pubDate>Mon, 08 Sep 2025 06:44:44 +0000</pubDate>
      <link>https://dev.to/techeazy_consulting/aws-elastic-load-balancer-elb-beginners-guide-1bg7</link>
      <guid>https://dev.to/techeazy_consulting/aws-elastic-load-balancer-elb-beginners-guide-1bg7</guid>
      <description>&lt;h2&gt;
  
  
  🌍 Introduction
&lt;/h2&gt;

&lt;p&gt;When you run an application on AWS, having just &lt;strong&gt;one server (EC2 instance)&lt;/strong&gt; is risky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If that server fails → your app goes down ❌&lt;/li&gt;
&lt;li&gt;If too many users visit → server may crash ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 That’s where &lt;strong&gt;Elastic Load Balancer (ELB)&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS ELB&lt;/strong&gt; automatically distributes traffic across multiple servers (EC2, containers, Lambda). This ensures:&lt;br&gt;
✅ High availability&lt;br&gt;
✅ Scalability&lt;br&gt;
✅ Fault tolerance&lt;/p&gt;

&lt;p&gt;By the end, you’ll understand:&lt;br&gt;
👉 &lt;strong&gt;Browser → ELB (smart routing + health checks) → Healthy Servers (EC2, ECS, Lambda)&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Step 1: Understand ELB Types
&lt;/h2&gt;

&lt;p&gt;AWS provides &lt;strong&gt;different types of load balancers&lt;/strong&gt; for different use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Application Load Balancer (ALB)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Works at &lt;strong&gt;Layer 7 (Application Layer)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Best for &lt;strong&gt;HTTP/HTTPS traffic&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Supports &lt;strong&gt;content-based routing&lt;/strong&gt; (host, path, headers)&lt;/li&gt;
&lt;li&gt;Example: &lt;code&gt;/api/*&lt;/code&gt; → API servers, &lt;code&gt;/images/*&lt;/code&gt; → image servers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2️⃣ Network Load Balancer (NLB)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Works at &lt;strong&gt;Layer 4 (Transport Layer)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Handles &lt;strong&gt;TCP/UDP/TLS traffic&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Extremely &lt;strong&gt;fast + scalable&lt;/strong&gt; (millions of requests/sec)&lt;/li&gt;
&lt;li&gt;Provides &lt;strong&gt;static IPs&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Example: gaming, IoT, high-performance apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3️⃣ Gateway Load Balancer (GWLB)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Works at &lt;strong&gt;Layer 3 (Network Layer)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;3rd-party appliances&lt;/strong&gt; (firewalls, intrusion detection)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4️⃣ Classic Load Balancer (CLB)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Legacy version&lt;/li&gt;
&lt;li&gt;Works at Layer 4 &amp;amp; 7 (limited features)&lt;/li&gt;
&lt;li&gt;⚠️ AWS recommends using ALB or NLB instead&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Step 2: Learn Key ELB Terminologies
&lt;/h2&gt;

&lt;p&gt;Here are the &lt;strong&gt;basic terms&lt;/strong&gt; you’ll see when setting up ELB:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Resource receiving traffic (EC2, Lambda, IP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target Group&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A pool of targets (with health checks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Listener&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Process that checks for connections (protocol + port)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Listener Rule&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routing conditions (e.g., &lt;code&gt;/api/*&lt;/code&gt; → API group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Health Check&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ELB test to ensure only healthy servers get traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AZ (Availability Zone)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AWS data centers where servers run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cross-Zone LB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Distribute traffic across all AZs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sticky Sessions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Keep same user on the same server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security Groups&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Firewall for ELB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle Timeout&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Time before idle connections close&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSL/TLS Cert&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enables HTTPS (via AWS ACM)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📜 Step 3: How ELB Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User&lt;/strong&gt; visits your app (e.g., &lt;code&gt;myapp.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Request goes to &lt;strong&gt;ELB Listener&lt;/strong&gt; (port 80 or 443)&lt;/li&gt;
&lt;li&gt;ELB checks &lt;strong&gt;Listener Rules&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ELB forwards request to the correct &lt;strong&gt;Target Group&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health Check&lt;/strong&gt; ensures only healthy servers receive traffic&lt;/li&gt;
&lt;li&gt;Response goes back → ELB → user&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 Flow: &lt;strong&gt;Browser → ELB → Healthy Server → ELB → Browser&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Step 4: Benefits of ELB
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Scalability&lt;/strong&gt; – Auto-scales with traffic&lt;br&gt;
✅ &lt;strong&gt;High Availability&lt;/strong&gt; – Multi-AZ support&lt;br&gt;
✅ &lt;strong&gt;Security&lt;/strong&gt; – SSL/TLS, WAF integration&lt;br&gt;
✅ &lt;strong&gt;Monitoring&lt;/strong&gt; – CloudWatch metrics, access logs&lt;br&gt;
✅ &lt;strong&gt;Cost Efficient&lt;/strong&gt; – Pay-as-you-go pricing&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Step 5: Real-World Example
&lt;/h2&gt;

&lt;p&gt;Imagine an &lt;strong&gt;E-commerce website&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run &lt;strong&gt;3 EC2 instances&lt;/strong&gt; in different AZs&lt;/li&gt;
&lt;li&gt;Deploy an &lt;strong&gt;Application Load Balancer&lt;/strong&gt; in front&lt;/li&gt;
&lt;li&gt;A user goes to &lt;code&gt;www.shop.com&lt;/code&gt; → ELB receives request&lt;/li&gt;
&lt;li&gt;ELB checks which server is healthy + least busy&lt;/li&gt;
&lt;li&gt;Routes request → Server responds → User gets page&lt;/li&gt;
&lt;li&gt;If one server crashes → traffic reroutes to healthy ones 🎉&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Conclusion
&lt;/h2&gt;

&lt;p&gt;With ELB, you get:&lt;/p&gt;

&lt;p&gt;✅ Better performance&lt;br&gt;
✅ Zero downtime (if a server fails)&lt;br&gt;
✅ Intelligent routing&lt;br&gt;
✅ Secure connections&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;For websites → ALB&lt;/strong&gt;&lt;br&gt;
👉 &lt;strong&gt;For high-performance TCP apps → NLB&lt;/strong&gt;&lt;br&gt;
👉 &lt;strong&gt;For firewalls/security → GWLB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;recommended AWS setup&lt;/strong&gt; for building highly available, production-grade applications 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Next Steps
&lt;/h2&gt;

&lt;p&gt;🚀 Be interview-ready in the era of AI &amp;amp; Cloud — start your DevOps journey today!&lt;br&gt;&lt;br&gt;
💡 YouTube won’t get you a job. Real projects + real internship certificate will.&lt;br&gt;&lt;br&gt;
🔥 AI is reshaping jobs. Don’t watch it happen, be part of it with DevOps &amp;amp; Cloud skills.&lt;br&gt;&lt;br&gt;
🎯 ₹2000/month today = Dream job tomorrow. Secure your spot now.&lt;br&gt;&lt;br&gt;
⏳ Every month you wait, Cloud + AI jobs are being filled. Don’t miss out!&lt;br&gt;&lt;br&gt;
🌐 DevOps + AWS + AI = The skillset every recruiter is hunting for in 2025.  &lt;/p&gt;

&lt;h2&gt;
  
  
  👉 Register now at &lt;a href="https://www.techeazyconsulting.com" rel="noopener noreferrer"&gt;TechEazy Consulting&lt;/a&gt;
&lt;/h2&gt;

</description>
      <category>aws</category>
      <category>elb</category>
      <category>devops</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
