<?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: Prakash Rao</title>
    <description>The latest articles on DEV Community by Prakash Rao (@prakash_rao).</description>
    <link>https://dev.to/prakash_rao</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%2F1595996%2Fc8b3c865-cb83-4f58-80ad-8e973a535876.jpg</url>
      <title>DEV Community: Prakash Rao</title>
      <link>https://dev.to/prakash_rao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prakash_rao"/>
    <language>en</language>
    <item>
      <title>x402 + MCP: where does the budget check go?</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Sat, 26 Sep 2026 09:06:14 +0000</pubDate>
      <link>https://dev.to/prakash_rao/x402-mcp-where-does-the-budget-check-go-4h06</link>
      <guid>https://dev.to/prakash_rao/x402-mcp-where-does-the-budget-check-go-4h06</guid>
      <description>&lt;p&gt;&lt;em&gt;By Prakash Rao Bethapudi and Marco Gonzalez&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An agent needs to enrich a customer record. The tool that does it costs money.&lt;/p&gt;

&lt;p&gt;Nothing in x402 v2 says who is allowed to approve that. Nothing in MCP 2026-07-28 says it either. Both specs moved price and routing metadata into HTTP headers, which means your gateway can now &lt;em&gt;see&lt;/em&gt; what a tool call costs. Seeing a price is not the same as having the authority to approve one.&lt;/p&gt;

&lt;p&gt;We wrote about where that authority should sit in &lt;a href="https://aaif.io/blog/402-payment-required-what-enterprise-mcp-servers-owe-the-agents-that-pay-them" rel="noopener noreferrer"&gt;402 Payment Required: What Enterprise MCP Servers Owe the Agents That Pay Them&lt;/a&gt;, with the Agentic AI Foundation. Then we took it to &lt;strong&gt;AGNTCon + MCPCon Japan&lt;/strong&gt; in Tokyo and let an agent actually do it, live, on a test network.&lt;/p&gt;

&lt;p&gt;If you missed either the post or the session, here is everything you need before we start.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, the catch-up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What x402 is.&lt;/strong&gt; HTTP has had a &lt;code&gt;402 Payment Required&lt;/code&gt; status code sitting unused since 1997, reserved but never specified. x402 finally gave it a meaning: a server answers &lt;code&gt;402&lt;/code&gt; with the terms it wants, the client retries with a signed payment authorization, and the server returns the result plus evidence of settlement. &lt;strong&gt;v2 (December 2025) moved all of that into headers&lt;/strong&gt;: &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt;, &lt;code&gt;PAYMENT-SIGNATURE&lt;/code&gt; and &lt;code&gt;PAYMENT-RESPONSE&lt;/code&gt;, instead of burying it in bodies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What MCP is.&lt;/strong&gt; The Model Context Protocol is how an AI agent discovers and calls tools. &lt;strong&gt;The 2026-07-28 revision&lt;/strong&gt; removed sessions and the &lt;code&gt;Mcp-Session-Id&lt;/code&gt; header, added &lt;code&gt;Mcp-Method&lt;/code&gt; and &lt;code&gt;Mcp-Name&lt;/code&gt; as headers, and hardened authorization with issuer validation per RFC 9207.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why those two releases matter together.&lt;/strong&gt; Both moved the interesting metadata &lt;em&gt;out of request bodies and into headers&lt;/em&gt;. Your gateway, rate limiter and WAF can now see who is calling, which tool, and what it costs, without parsing a single JSON-RPC body. Metering and routing for paid agent traffic got dramatically cheaper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that is exactly where the problem starts.&lt;/strong&gt; Header visibility is not authority. The moment your infrastructure can see the price, it has to decide something about it, and neither spec tells you who gets to make that call. That was the argument in &lt;a href="https://aaif.io/blog/402-payment-required-what-enterprise-mcp-servers-owe-the-agents-that-pay-them" rel="noopener noreferrer"&gt;our AAIF post&lt;/a&gt;: the spending decision belongs to a budget authority the agent cannot reach, and where you put it is the part that will still matter after the protocol details have moved on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we did in Tokyo.&lt;/strong&gt; Stopped arguing and ran it: a live agent paying for MCP tool calls on a test network, including the path where it tries to spend on something it was not approved for.&lt;/p&gt;

&lt;h3&gt;
  
  
  The cast
&lt;/h3&gt;

&lt;p&gt;Five moving parts appear throughout. You do not need to memorize these; they are here so the diagrams read cleanly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Its one job&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Decides what work to do. Treated as hostile throughout. Holds no private key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enforcement gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The only permitted route out. Sees every request twice and can refuse at the boundary.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authorization service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Decides whether spending is permitted, and reserves the budget. The agent cannot influence it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Signing service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Produces signatures. Reads what it signs, and can refuse.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Protected resource&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The tool that costs money, behind a paid server.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Our threat model, so you know what is and is not being defended: the &lt;strong&gt;agent process and every input to it are hostile&lt;/strong&gt;. The gateway, the services and their policies are &lt;strong&gt;honest but fallible&lt;/strong&gt;. Compromised binaries, malicious operators, key extraction from hardware and chain-level attacks are &lt;strong&gt;out of scope&lt;/strong&gt;. Different problem, different post.&lt;/p&gt;

&lt;p&gt;Now follow one request all the way through. It gets interesting about two-thirds of the way down, when the request that arrives at the boundary turns out not to be the request that was approved.&lt;/p&gt;




&lt;h2&gt;
  
  
  The agent goes shopping
&lt;/h2&gt;

&lt;p&gt;Our agent has a task stated in business terms: &lt;em&gt;enrich record 42&lt;/em&gt;. It does not know what that costs, and it does not know which provider will do it.&lt;/p&gt;

&lt;p&gt;So the first problem is immediate: how do you let a hostile thing shop around, without handing it a wallet first?&lt;/p&gt;

&lt;p&gt;It asks, and gets refused on purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/tools/enrich?record=42&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resource.example&lt;/span&gt;

HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: eyJ2IjoyLCJhY2NlcHRzIjpbey...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That header is base64 JSON. Decoded, it is an offer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accepts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scheme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"exact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;test-network&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"asset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;stablecoin-contract&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"payTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;payee-address&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"maxAmountRequired"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;amount&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://resource.example/tools/enrich"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"maxTimeoutSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;server-chosen&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the HTTP binding. Over MCP the same negotiation happens, but not in the same place. Worth knowing before you meter anything at the edge:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;HTTP binding&lt;/th&gt;
&lt;th&gt;MCP binding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Price challenge arrives as&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;402&lt;/code&gt; status + &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;terms in the &lt;strong&gt;tool result&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routing metadata&lt;/td&gt;
&lt;td&gt;the URL path&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Mcp-Method&lt;/code&gt; / &lt;code&gt;Mcp-Name&lt;/code&gt; headers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visible to infra without parsing a body&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;the challenge is &lt;strong&gt;not&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The MCP binding hands your gateway a &lt;code&gt;200&lt;/code&gt; for a call nobody has paid for yet. If your metering logic keys on status codes, it will sail straight past that.&lt;/p&gt;

&lt;p&gt;Here is the first design decision that matters more than it looks. &lt;strong&gt;Asking is free.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If finding out what something costs itself costs money, then every agent needs spending authority &lt;em&gt;before&lt;/em&gt; it can plan, which pushes the authorization decision to the least informed moment in the entire flow. Free discovery is what lets this first pass carry no authority to consume value at all. The boundary can admit it precisely because admitting it commits the organization to nothing.&lt;/p&gt;

&lt;p&gt;And because this pass is cheap to allow, the boundary can do something quietly important while it is forwarding:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant W as Agent
    participant G as Enforcement gateway
    participant R as Protected resource

    W-&amp;gt;&amp;gt;G: candidate request, identity present,&amp;lt;br/&amp;gt;no authority to consume value
    G-&amp;gt;&amp;gt;G: validate assertion, apply a lighter policy
    G-&amp;gt;&amp;gt;G: audience translation: mint a downstream credential&amp;lt;br/&amp;gt;scoped to one resource and one action
    G-&amp;gt;&amp;gt;R: forward, carrying only that credential
    R--&amp;gt;&amp;gt;G: resource-terms response, the quote
    G-&amp;gt;&amp;gt;G: record the witnessed terms, from the return leg
    G--&amp;gt;&amp;gt;W: the quote&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The gateway &lt;strong&gt;saw the quote itself&lt;/strong&gt;, on the way back. Remember that. It becomes the whole game at the boundary.&lt;/p&gt;

&lt;p&gt;Note also what crossed the boundary: not the enterprise credential, but a freshly minted one restricted to one resource and one action. Useful for nothing else. That is audience translation, and it is how you avoid handing a downstream service something it could turn around and reuse.&lt;/p&gt;




&lt;h2&gt;
  
  
  Someone has to approve it
&lt;/h2&gt;

&lt;p&gt;Now the agent wants to actually do it. This is the moment the money becomes real, and the moment somebody other than the agent has to say yes.&lt;/p&gt;

&lt;p&gt;Four decisions are tangled together here, and the useful move is to pull them apart and give each one an owner:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Who owns it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What work to do&lt;/td&gt;
&lt;td&gt;the agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Who is asking&lt;/td&gt;
&lt;td&gt;identity provider, at the gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What it costs&lt;/td&gt;
&lt;td&gt;the resource server, from the arguments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Whether it is permitted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;a budget authority the agent cannot reach&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That last row is the one people collapse, and collapsing it is how an agent ends up able to approve its own spending.&lt;/p&gt;

&lt;p&gt;The authorization service does four things in order. Each one is load-bearing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It fetches the quote from the gateway, never from the request.&lt;/strong&gt; The agent is hostile; its claim about what it was offered is worthless. The boundary witnessed the real terms while the agent was shopping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It filters on capability before it looks at price.&lt;/strong&gt; Capability and compliance narrow the field first. A filter, not a ranking. No price advantage restores an excluded candidate. Get this backwards and you have a system that will happily route regulated data somewhere cheap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It reserves the budget before any attempt is made&lt;/strong&gt;, as one indivisible state transition. This is what stops concurrent agents sharing an allocation from collectively overspending it: the commitment is taken up front rather than discovered afterwards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then it binds the whole meaning of the action into one digest, and signs a receipt over it.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// authorization service&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deriveActionFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;witnessedTerms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;digest&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;canonicalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;   &lt;span class="c1"&gt;// RFC 8785 serialization&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;reserveAtomically&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allocation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ceiling&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// before any attempt&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signReceipt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                                        &lt;span class="c1"&gt;// the binding&lt;/span&gt;
  &lt;span class="nx"&gt;policyVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;expiresAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;SHORT_TTL&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One binding, over the whole meaning of the action. Alter any bound element and the digest differs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The signer that can still say no
&lt;/h2&gt;

&lt;p&gt;The agent has a receipt. It needs a signature. And here the architecture does something that surprises people:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The component that approved the action cannot sign it. The component that signs it can still refuse.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// policy-aware signing service&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseStructuredPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// it can read what it signs&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;recoverConsequentialParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;withinOwnConstraints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;refuse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constraint_violation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// even though the gate approved&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;signWithNonExportableKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A custody service that signs an opaque digest enforces nothing about meaning. Handed a blob, it has no basis on which to form an opinion at all. This one parses the payload first, recovers the parameters that actually matter, and applies its own constraints. It can refuse an action the authorization gate already approved.&lt;/p&gt;

&lt;p&gt;Meanwhile the gate holds no key whatsoever. It is &lt;em&gt;incapable&lt;/em&gt; of producing a signature. That is not a policy choice you can accidentally configure away. It is a property of who holds what.&lt;/p&gt;

&lt;p&gt;There is a boring reason this split survives contact with a roadmap, and it persuades engineers faster than the security argument: the rules about what a key may be used for and the rules about what policy permits change at different rates, for different reasons, owned by different teams. Putting them in one component means every policy change touches the thing holding your keys. Nobody wants that.&lt;/p&gt;




&lt;h2&gt;
  
  
  And then it gets refused
&lt;/h2&gt;

&lt;p&gt;The signed request heads for the exit. The receipt is valid. The signature verifies.&lt;/p&gt;

&lt;p&gt;And the boundary refuses it.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant W as Agent
    participant G as Enforcement gateway
    participant R as Protected resource

    W-&amp;gt;&amp;gt;G: authorized request + valid receipt
    Note right of W: something changed after approval
    G-&amp;gt;&amp;gt;G: re-derive the action from the bytes that will actually leave
    G-&amp;gt;&amp;gt;G: recompute the digest
    G--xW: DENIED: mismatch, fail closed
    Note over G,R: nothing leaves&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Here is why, and it is the single most important line in the whole design:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gateway does not read the digest out of the receipt. It rebuilds it from the bytes that are actually leaving.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// enforcement gateway, egress path&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;verifySignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad_receipt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expired_receipt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Re-derive from the request that will actually leave, not from the receipt.&lt;/span&gt;
  &lt;span class="c1"&gt;// RFC 8785 fixes the serialization; a normative rule both sides build&lt;/span&gt;
  &lt;span class="c1"&gt;// against fixes which fields participate.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rebuilt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;canonicalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;deriveActionFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rebuilt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;digest_mismatch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// substituted, or altered after approval&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// A valid receipt is necessary, not sufficient.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;deriveActionFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translateAudience&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two independent opinions have to agree. One was formed at approval time, from the proposal; the other is formed here, from reality. Verifying a &lt;em&gt;decision&lt;/em&gt; is not the same as verifying the &lt;em&gt;thing the decision was about&lt;/em&gt;, and almost every system that gets this wrong gets it wrong right here.&lt;/p&gt;

&lt;p&gt;Notice what a mismatch catches in both directions. Substituting to a more expensive resource is a budget failure. Substituting to a &lt;em&gt;cheaper&lt;/em&gt; one can send regulated data somewhere not approved for it. Same mismatch, same refusal.&lt;/p&gt;

&lt;p&gt;And notice &lt;code&gt;failClosed&lt;/code&gt; on every path. Where required verification cannot be completed, the request is denied. A verifier that cannot answer is never treated as one that said yes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Settling up
&lt;/h2&gt;

&lt;p&gt;When a request does pass, the ending is deliberately unglamorous. The agent signs the value authorization but submits nothing; a facilitator submits it and bears the execution fee, so the workload needs no local balance of any kind, of any asset. Then one trace identifier binds the identity subject, the signing request, the nonce and the settlement record together, so a completed action can be reconstructed end to end from evidence held entirely &lt;em&gt;outside&lt;/em&gt; the agent.&lt;/p&gt;

&lt;p&gt;Neither direction requires trusting it. That is the point.&lt;/p&gt;

&lt;p&gt;Here is the whole path, once, now that you know what each step is defending against:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant W as Agent
    participant G as Enforcement gateway
    participant A as Authorization service
    participant S as Signing service
    participant R as Protected resource

    Note over W,R: DISCOVERY, no authority to spend
    W-&amp;gt;&amp;gt;G: discovery pass, no authority to consume value
    G-&amp;gt;&amp;gt;R: forward with a scoped downstream credential
    R--&amp;gt;&amp;gt;G: the quote
    G-&amp;gt;&amp;gt;G: record the witnessed terms

    Note over W,R: AUTHORIZATION
    W-&amp;gt;&amp;gt;A: request authorization
    A-&amp;gt;&amp;gt;G: fetch witnessed terms, never from the request
    A-&amp;gt;&amp;gt;A: capability filter, then cost
    A-&amp;gt;&amp;gt;A: reserve atomically, before any attempt
    A--&amp;gt;&amp;gt;W: signed receipt, bound to the digest

    Note over W,R: SIGNING
    W-&amp;gt;&amp;gt;S: request a signature
    S-&amp;gt;&amp;gt;S: parse, recover parameters, enforce own constraints
    S--&amp;gt;&amp;gt;W: signature from a non-exportable key

    Note over W,R: EGRESS
    W-&amp;gt;&amp;gt;G: authorized request + receipt
    G-&amp;gt;&amp;gt;G: re-derive from outgoing bytes, recompute digest
    G-&amp;gt;&amp;gt;G: independent policy re-evaluation
    G-&amp;gt;&amp;gt;R: release, or refuse&lt;/code&gt;&lt;/pre&gt;






&lt;h2&gt;
  
  
  What the stage taught us
&lt;/h2&gt;

&lt;p&gt;Three things we did not fully appreciate until it was running in front of people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The refusal is the demo.&lt;/strong&gt; We prepared a success path and a denial path and rehearsed the success path harder. That was backwards. An authorization architecture is most convincing at the moment nothing happens. The receipt is valid, the signature is good, and the request still does not leave. If you demo one of these, budget your stage time for the refusal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Canonicalization determinism is not a detail, it is the design.&lt;/strong&gt; Two independent derivations only help if they agree. RFC 8785 fixes &lt;em&gt;how&lt;/em&gt; to serialize; it does not fix &lt;em&gt;which fields participate&lt;/em&gt;. Every ambiguity you leave in that question becomes a future incident that presents as a mysterious denial and resolves three layers away. Write the membership rule down as a normative artifact both sides build against, not as behaviour each side reimplements from prose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reachability is not authority.&lt;/strong&gt; The agent in this flow calls the authorization service over an ordinary API, like any client. It simply cannot move its own limit. An agent that cannot reach the authorization service is isolated; an agent that reaches it and still cannot change the answer is governed. Those are very different systems and only one of them is useful.&lt;/p&gt;

&lt;p&gt;Neither x402 v2 nor MCP 2026-07-28 makes the spending decision for you. They make the price visible and the routing cheap. Where the authority sits is still yours to place, and that placement will outlive both protocols.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aaif.io/blog/402-payment-required-what-enterprise-mcp-servers-owe-the-agents-that-pay-them" rel="noopener noreferrer"&gt;AAIF post&lt;/a&gt; has the full argument and the five obligations a paid tool server owes its callers.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Code is illustrative and abbreviated to the checks under discussion.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Patent pending. U.S. Provisional Application No. 64/149,249, filed 6 September 2026 (docket Y26S008-PPA)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>architecture</category>
      <category>security</category>
    </item>
    <item>
      <title>x402 + MCP: where does the budget check go?</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Fri, 25 Sep 2026 18:19:17 +0000</pubDate>
      <link>https://dev.to/prakash_rao/watch-an-ai-agent-try-to-spend-money-it-shouldnt-2754</link>
      <guid>https://dev.to/prakash_rao/watch-an-ai-agent-try-to-spend-money-it-shouldnt-2754</guid>
      <description>&lt;p&gt;&lt;em&gt;By Prakash Rao Bethapudi and Marco Gonzalez&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An agent needs to enrich a customer record. The tool that does it costs money.&lt;/p&gt;

&lt;p&gt;Nothing in x402 v2 says who is allowed to approve that. Nothing in MCP 2026-07-28 says it either. Both specs moved price and routing metadata into HTTP headers, which means your gateway can now &lt;em&gt;see&lt;/em&gt; what a tool call costs. Seeing a price is not the same as having the authority to approve one.&lt;/p&gt;

&lt;p&gt;We wrote about where that authority should sit in &lt;a href="https://aaif.io/blog/402-payment-required-what-enterprise-mcp-servers-owe-the-agents-that-pay-them" rel="noopener noreferrer"&gt;402 Payment Required: What Enterprise MCP Servers Owe the Agents That Pay Them&lt;/a&gt;, with the Agentic AI Foundation. Then we took it to AGNTCon + MCPCon Japan in Tokyo and let an agent actually do it, live, on a test network.&lt;/p&gt;

&lt;p&gt;If you missed either the post or the session, here is everything you need before we start.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, the catch-up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What x402 is.&lt;/strong&gt; HTTP has had a &lt;code&gt;402 Payment Required&lt;/code&gt; status code sitting unused since 1997, reserved but never specified. x402 finally gave it a meaning: a server answers &lt;code&gt;402&lt;/code&gt; with the terms it wants, the client retries with a signed payment authorization, and the server returns the result plus evidence of settlement. &lt;strong&gt;v2 (December 2025) moved all of that into headers&lt;/strong&gt;: &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt;, &lt;code&gt;PAYMENT-SIGNATURE&lt;/code&gt; and &lt;code&gt;PAYMENT-RESPONSE&lt;/code&gt;, instead of burying it in bodies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What MCP is.&lt;/strong&gt; The Model Context Protocol is how an AI agent discovers and calls tools. &lt;strong&gt;The 2026-07-28 revision&lt;/strong&gt; removed sessions and the &lt;code&gt;Mcp-Session-Id&lt;/code&gt; header, added &lt;code&gt;Mcp-Method&lt;/code&gt; and &lt;code&gt;Mcp-Name&lt;/code&gt; as headers, and hardened authorization with issuer validation per RFC 9207.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why those two releases matter together.&lt;/strong&gt; Both moved the interesting metadata &lt;em&gt;out of request bodies and into headers&lt;/em&gt;. Your gateway, rate limiter and WAF can now see who is calling, which tool, and what it costs, without parsing a single JSON-RPC body. Metering and routing for paid agent traffic got dramatically cheaper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that is exactly where the problem starts.&lt;/strong&gt; Header visibility is not authority. The moment your infrastructure can see the price, it has to decide something about it, and neither spec tells you who gets to make that call. That was the argument in &lt;a href="https://aaif.io/blog/402-payment-required-what-enterprise-mcp-servers-owe-the-agents-that-pay-them" rel="noopener noreferrer"&gt;our AAIF post&lt;/a&gt;: the spending decision belongs to a budget authority the agent cannot reach, and where you put it is the part that will still matter after the protocol details have moved on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we did in Tokyo.&lt;/strong&gt; Stopped arguing and ran it: a live agent paying for MCP tool calls on a test network, including the path where it tries to spend on something it was not approved for.&lt;/p&gt;

&lt;h3&gt;
  
  
  The cast
&lt;/h3&gt;

&lt;p&gt;Five moving parts appear throughout. You do not need to memorize these; they are here so the diagrams read cleanly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Its one job&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Decides what work to do. Treated as hostile throughout. Holds no private key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enforcement gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The only permitted route out. Sees every request twice and can refuse at the boundary.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authorization service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Decides whether spending is permitted, and reserves the budget. The agent cannot influence it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Signing service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Produces signatures. Reads what it signs, and can refuse.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Protected resource&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The tool that costs money, behind a paid server.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Our threat model, so you know what is and is not being defended: the &lt;strong&gt;agent process and every input to it are hostile&lt;/strong&gt;. The gateway, the services and their policies are &lt;strong&gt;honest but fallible&lt;/strong&gt;. Compromised binaries, malicious operators, key extraction from hardware and chain-level attacks are &lt;strong&gt;out of scope&lt;/strong&gt;. Different problem, different post.&lt;/p&gt;

&lt;p&gt;Now follow one request all the way through. It gets interesting about two-thirds of the way down, when the request that arrives at the boundary turns out not to be the request that was approved.&lt;/p&gt;




&lt;h2&gt;
  
  
  The agent goes shopping
&lt;/h2&gt;

&lt;p&gt;Our agent has a task stated in business terms: &lt;em&gt;enrich record 42&lt;/em&gt;. It does not know what that costs, and it does not know which provider will do it.&lt;/p&gt;

&lt;p&gt;So the first problem is immediate: how do you let a hostile thing shop around, without handing it a wallet first?&lt;/p&gt;

&lt;p&gt;It asks, and gets refused on purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/tools/enrich?record=42&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resource.example&lt;/span&gt;

HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: eyJ2IjoyLCJhY2NlcHRzIjpbey...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That header is base64 JSON. Decoded, it is an offer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accepts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scheme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"exact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;test-network&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"asset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;stablecoin-contract&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"payTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;payee-address&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"maxAmountRequired"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;amount&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://resource.example/tools/enrich"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"maxTimeoutSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;server-chosen&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the HTTP binding. Over MCP the same negotiation happens, but not in the same place. Worth knowing before you meter anything at the edge:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;HTTP binding&lt;/th&gt;
&lt;th&gt;MCP binding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Price challenge arrives as&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;402&lt;/code&gt; status + &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;terms in the &lt;strong&gt;tool result&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routing metadata&lt;/td&gt;
&lt;td&gt;the URL path&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Mcp-Method&lt;/code&gt; / &lt;code&gt;Mcp-Name&lt;/code&gt; headers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visible to infra without parsing a body&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;the challenge is &lt;strong&gt;not&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The MCP binding hands your gateway a &lt;code&gt;200&lt;/code&gt; for a call nobody has paid for yet. If your metering logic keys on status codes, it will sail straight past that.&lt;/p&gt;

&lt;p&gt;Here is the first design decision that matters more than it looks. &lt;strong&gt;Asking is free.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If finding out what something costs itself costs money, then every agent needs spending authority &lt;em&gt;before&lt;/em&gt; it can plan, which pushes the authorization decision to the least informed moment in the entire flow. Free discovery is what lets this first pass carry no authority to consume value at all. The boundary can admit it precisely because admitting it commits the organization to nothing.&lt;/p&gt;

&lt;p&gt;And because this pass is cheap to allow, the boundary can do something quietly important while it is forwarding:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant W as Agent
    participant G as Enforcement gateway
    participant R as Protected resource

    W-&amp;gt;&amp;gt;G: candidate request, identity present,&amp;lt;br/&amp;gt;no authority to consume value
    G-&amp;gt;&amp;gt;G: validate assertion, apply a lighter policy
    G-&amp;gt;&amp;gt;G: audience translation: mint a downstream credential&amp;lt;br/&amp;gt;scoped to one resource and one action
    G-&amp;gt;&amp;gt;R: forward, carrying only that credential
    R--&amp;gt;&amp;gt;G: resource-terms response, the quote
    G-&amp;gt;&amp;gt;G: record the witnessed terms, from the return leg
    G--&amp;gt;&amp;gt;W: the quote&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The gateway &lt;strong&gt;saw the quote itself&lt;/strong&gt;, on the way back. Remember that. It becomes the whole game at the boundary.&lt;/p&gt;

&lt;p&gt;Note also what crossed the boundary: not the enterprise credential, but a freshly minted one restricted to one resource and one action. Useful for nothing else. That is audience translation, and it is how you avoid handing a downstream service something it could turn around and reuse.&lt;/p&gt;




&lt;h2&gt;
  
  
  Someone has to approve it
&lt;/h2&gt;

&lt;p&gt;Now the agent wants to actually do it. This is the moment the money becomes real, and the moment somebody other than the agent has to say yes.&lt;/p&gt;

&lt;p&gt;Four decisions are tangled together here, and the useful move is to pull them apart and give each one an owner:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Who owns it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What work to do&lt;/td&gt;
&lt;td&gt;the agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Who is asking&lt;/td&gt;
&lt;td&gt;identity provider, at the gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What it costs&lt;/td&gt;
&lt;td&gt;the resource server, from the arguments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Whether it is permitted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;a budget authority the agent cannot reach&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That last row is the one people collapse, and collapsing it is how an agent ends up able to approve its own spending.&lt;/p&gt;

&lt;p&gt;The authorization service does four things in order. Each one is load-bearing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It fetches the quote from the gateway, never from the request.&lt;/strong&gt; The agent is hostile; its claim about what it was offered is worthless. The boundary witnessed the real terms while the agent was shopping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It filters on capability before it looks at price.&lt;/strong&gt; Capability and compliance narrow the field first. A filter, not a ranking. No price advantage restores an excluded candidate. Get this backwards and you have a system that will happily route regulated data somewhere cheap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It reserves the budget before any attempt is made&lt;/strong&gt;, as one indivisible state transition. This is what stops concurrent agents sharing an allocation from collectively overspending it: the commitment is taken up front rather than discovered afterwards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then it binds the whole meaning of the action into one digest, and signs a receipt over it.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// authorization service&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deriveActionFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;witnessedTerms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;digest&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;canonicalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;   &lt;span class="c1"&gt;// RFC 8785 serialization&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;reserveAtomically&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allocation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ceiling&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// before any attempt&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signReceipt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;allow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                                        &lt;span class="c1"&gt;// the binding&lt;/span&gt;
  &lt;span class="nx"&gt;policyVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;expiresAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;SHORT_TTL&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One binding, over the whole meaning of the action. Alter any bound element and the digest differs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The signer that can still say no
&lt;/h2&gt;

&lt;p&gt;The agent has a receipt. It needs a signature. And here the architecture does something that surprises people:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The component that approved the action cannot sign it. The component that signs it can still refuse.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// policy-aware signing service&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseStructuredPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// it can read what it signs&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;recoverConsequentialParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;withinOwnConstraints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;refuse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constraint_violation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// even though the gate approved&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;signWithNonExportableKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A custody service that signs an opaque digest enforces nothing about meaning. Handed a blob, it has no basis on which to form an opinion at all. This one parses the payload first, recovers the parameters that actually matter, and applies its own constraints. It can refuse an action the authorization gate already approved.&lt;/p&gt;

&lt;p&gt;Meanwhile the gate holds no key whatsoever. It is &lt;em&gt;incapable&lt;/em&gt; of producing a signature. That is not a policy choice you can accidentally configure away. It is a property of who holds what.&lt;/p&gt;

&lt;p&gt;There is a boring reason this split survives contact with a roadmap, and it persuades engineers faster than the security argument: the rules about what a key may be used for and the rules about what policy permits change at different rates, for different reasons, owned by different teams. Putting them in one component means every policy change touches the thing holding your keys. Nobody wants that.&lt;/p&gt;




&lt;h2&gt;
  
  
  And then it gets refused
&lt;/h2&gt;

&lt;p&gt;The signed request heads for the exit. The receipt is valid. The signature verifies.&lt;/p&gt;

&lt;p&gt;And the boundary refuses it.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant W as Agent
    participant G as Enforcement gateway
    participant R as Protected resource

    W-&amp;gt;&amp;gt;G: authorized request + valid receipt
    Note right of W: something changed after approval
    G-&amp;gt;&amp;gt;G: re-derive the action from the bytes that will actually leave
    G-&amp;gt;&amp;gt;G: recompute the digest
    G--xW: DENIED: mismatch, fail closed
    Note over G,R: nothing leaves&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Here is why, and it is the single most important line in the whole design:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gateway does not read the digest out of the receipt. It rebuilds it from the bytes that are actually leaving.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// enforcement gateway, egress path&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;verifySignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad_receipt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;expired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expired_receipt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Re-derive from the request that will actually leave, not from the receipt.&lt;/span&gt;
  &lt;span class="c1"&gt;// RFC 8785 fixes the serialization; a normative rule both sides build&lt;/span&gt;
  &lt;span class="c1"&gt;// against fixes which fields participate.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rebuilt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;canonicalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;deriveActionFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rebuilt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;receipt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;digest_mismatch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// substituted, or altered after approval&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// A valid receipt is necessary, not sufficient.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;deriveActionFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;failClosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translateAudience&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two independent opinions have to agree. One was formed at approval time, from the proposal; the other is formed here, from reality. Verifying a &lt;em&gt;decision&lt;/em&gt; is not the same as verifying the &lt;em&gt;thing the decision was about&lt;/em&gt;, and almost every system that gets this wrong gets it wrong right here.&lt;/p&gt;

&lt;p&gt;Notice what a mismatch catches in both directions. Substituting to a more expensive resource is a budget failure. Substituting to a &lt;em&gt;cheaper&lt;/em&gt; one can send regulated data somewhere not approved for it. Same mismatch, same refusal.&lt;/p&gt;

&lt;p&gt;And notice &lt;code&gt;failClosed&lt;/code&gt; on every path. Where required verification cannot be completed, the request is denied. A verifier that cannot answer is never treated as one that said yes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Settling up
&lt;/h2&gt;

&lt;p&gt;When a request does pass, the ending is deliberately unglamorous. The agent signs the value authorization but submits nothing; a facilitator submits it and bears the execution fee, so the workload needs no local balance of any kind, of any asset. Then one trace identifier binds the identity subject, the signing request, the nonce and the settlement record together, so a completed action can be reconstructed end to end from evidence held entirely &lt;em&gt;outside&lt;/em&gt; the agent.&lt;/p&gt;

&lt;p&gt;Neither direction requires trusting it. That is the point.&lt;/p&gt;

&lt;p&gt;Here is the whole path, once, now that you know what each step is defending against:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;sequenceDiagram
    autonumber
    participant W as Agent
    participant G as Enforcement gateway
    participant A as Authorization service
    participant S as Signing service
    participant R as Protected resource

    Note over W,R: DISCOVERY, no authority to spend
    W-&amp;gt;&amp;gt;G: discovery pass, no authority to consume value
    G-&amp;gt;&amp;gt;R: forward with a scoped downstream credential
    R--&amp;gt;&amp;gt;G: the quote
    G-&amp;gt;&amp;gt;G: record the witnessed terms

    Note over W,R: AUTHORIZATION
    W-&amp;gt;&amp;gt;A: request authorization
    A-&amp;gt;&amp;gt;G: fetch witnessed terms, never from the request
    A-&amp;gt;&amp;gt;A: capability filter, then cost
    A-&amp;gt;&amp;gt;A: reserve atomically, before any attempt
    A--&amp;gt;&amp;gt;W: signed receipt, bound to the digest

    Note over W,R: SIGNING
    W-&amp;gt;&amp;gt;S: request a signature
    S-&amp;gt;&amp;gt;S: parse, recover parameters, enforce own constraints
    S--&amp;gt;&amp;gt;W: signature from a non-exportable key

    Note over W,R: EGRESS
    W-&amp;gt;&amp;gt;G: authorized request + receipt
    G-&amp;gt;&amp;gt;G: re-derive from outgoing bytes, recompute digest
    G-&amp;gt;&amp;gt;G: independent policy re-evaluation
    G-&amp;gt;&amp;gt;R: release, or refuse&lt;/code&gt;&lt;/pre&gt;






&lt;h2&gt;
  
  
  What the stage taught us
&lt;/h2&gt;

&lt;p&gt;Three things we did not fully appreciate until it was running in front of people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The refusal is the demo.&lt;/strong&gt; We prepared a success path and a denial path and rehearsed the success path harder. That was backwards. An authorization architecture is most convincing at the moment nothing happens. The receipt is valid, the signature is good, and the request still does not leave. If you demo one of these, budget your stage time for the refusal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Canonicalization determinism is not a detail, it is the design.&lt;/strong&gt; Two independent derivations only help if they agree. RFC 8785 fixes &lt;em&gt;how&lt;/em&gt; to serialize; it does not fix &lt;em&gt;which fields participate&lt;/em&gt;. Every ambiguity you leave in that question becomes a future incident that presents as a mysterious denial and resolves three layers away. Write the membership rule down as a normative artifact both sides build against, not as behaviour each side reimplements from prose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reachability is not authority.&lt;/strong&gt; The agent in this flow calls the authorization service over an ordinary API, like any client. It simply cannot move its own limit. An agent that cannot reach the authorization service is isolated; an agent that reaches it and still cannot change the answer is governed. Those are very different systems and only one of them is useful.&lt;/p&gt;

&lt;p&gt;Neither x402 v2 nor MCP 2026-07-28 makes the spending decision for you. They make the price visible and the routing cheap. Where the authority sits is still yours to place, and that placement will outlive both protocols.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aaif.io/blog/402-payment-required-what-enterprise-mcp-servers-owe-the-agents-that-pay-them" rel="noopener noreferrer"&gt;AAIF post&lt;/a&gt; has the full argument and the five obligations a paid tool server owes its callers.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Code is illustrative and abbreviated to the checks under discussion.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Patent pending. U.S. Provisional Application No. 64/149,249, filed 6 September 2026 (docket Y26S008-PPA). A provisional application only: no patent has been granted and no patent number is asserted.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>architecture</category>
      <category>security</category>
    </item>
    <item>
      <title>Optimizing Performance and Cost on AWS: Strategies for Large-Scale Environments</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Wed, 12 Feb 2025 13:15:07 +0000</pubDate>
      <link>https://dev.to/prakash_rao/optimizing-performance-and-cost-on-aws-strategies-for-large-scale-environments-20jj</link>
      <guid>https://dev.to/prakash_rao/optimizing-performance-and-cost-on-aws-strategies-for-large-scale-environments-20jj</guid>
      <description>&lt;p&gt;In this post, I will walk through a series of strategies based on my experience to optimize both performance and cost in large-scale AWS environments. This will be the agenda:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto Scaling Configuration:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a launch template using a recommended instance type.&lt;/li&gt;
&lt;li&gt;Set up an ASG with defined minimum/maximum sizes and specific scaling thresholds.&lt;/li&gt;
&lt;li&gt;Define scaling policies and create CloudWatch alarms with real input values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Performance Tuning of Compute Services:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilize AWS Compute Optimizer to identify underutilized instances and determine right-sizing opportunities.
&lt;/li&gt;
&lt;li&gt;Set up custom CloudWatch metrics to monitor application performance (e.g., request latency) and trigger alerts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost Optimization Strategies:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query detailed cost data using AWS Cost Explorer to understand spending patterns.
&lt;/li&gt;
&lt;li&gt;Combine Compute Optimizer insights with reserved and spot instance strategies for significant cost reductions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Measurable Business Impact:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Review the impact on resource utilization, cost savings, and overall performance improvements based on these optimizations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to give actionable, real-world inputs and concrete CLI examples to achieve measurable business impact.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: All commands assume that you have the &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" rel="noopener noreferrer"&gt;AWS CLI&lt;/a&gt; installed and configured with the appropriate IAM permissions.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Auto Scaling: Fine-Tuning for Demand
&lt;/h2&gt;

&lt;p&gt;Auto scaling ensures that our applications maintain optimal performance while reducing idle capacity. Below are the steps with concrete inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Create a Launch Template with a Recommended Instance Type&lt;/strong&gt;&lt;br&gt;
Based on historical load patterns, let's choose a &lt;strong&gt;t3.medium&lt;/strong&gt; instance as our baseline. If analysis via &lt;em&gt;Compute Optimizer&lt;/em&gt; indicates underutilization, switch to a &lt;strong&gt;t3.small&lt;/strong&gt; or leveraging spot instances can be considered for non-critical workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command:&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 ec2 create-launch-template &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--launch-template-name&lt;/span&gt; MyWebAppTemplate &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--version-description&lt;/span&gt; &lt;span class="s2"&gt;"v1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--launch-template-data&lt;/span&gt; &lt;span class="s1"&gt;'{
      "ImageId": "ami-0abcdef1234567890",
      "InstanceType": "t3.medium",
      "KeyName": "my-key-pair",
      "SecurityGroupIds": ["sg-0123456789abcdef0"],
      "UserData": "IyEvYmluL2Jhc2gKZWNobyAiU3RhcnRpbmcgd2Vic2l0ZSBhcHAtZmxvdy4uLiIK"
    }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"LaunchTemplate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"LaunchTemplateId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lt-0123456789abcdef0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"LaunchTemplateName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MyWebAppTemplate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"DefaultVersionNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;B. Create an Auto Scaling Group with Specific Thresholds&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set up an ASG with a &lt;strong&gt;minimum size of 2&lt;/strong&gt; and &lt;strong&gt;maximum size of 10&lt;/strong&gt;. My recommendations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scale-Out:&lt;/strong&gt; Trigger when average CPU utilization exceeds &lt;strong&gt;70%&lt;/strong&gt; for two consecutive 5‑minute periods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale-In:&lt;/strong&gt; Trigger when average CPU utilization drops below &lt;strong&gt;30%&lt;/strong&gt; for two consecutive 5‑minute periods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Command:&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 autoscaling create-auto-scaling-group &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--auto-scaling-group-name&lt;/span&gt; MyWebAppASG &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--launch-template&lt;/span&gt; &lt;span class="s2"&gt;"LaunchTemplateId=lt-0123456789abcdef0,Version=1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--min-size&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--max-size&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--desired-capacity&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-zone-identifier&lt;/span&gt; &lt;span class="s2"&gt;"subnet-12345678,subnet-87654321"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ActivityId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abcdef12-3456-7890-abcd-ef1234567890"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C. Define Scaling Policies and CloudWatch Alarms with Real Inputs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scale-Out Policy Command:&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 autoscaling put-scaling-policy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--auto-scaling-group-name&lt;/span&gt; MyWebAppASG &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--policy-name&lt;/span&gt; ScaleOutPolicy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scaling-adjustment&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--adjustment-type&lt;/span&gt; ChangeInCapacity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"PolicyARN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:autoscaling:us-east-1:123456789012:scalingPolicy:abcdef12-3456-7890-abcd-ef1234567890:autoScalingGroupName/MyWebAppASG:policyName/ScaleOutPolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"PolicyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ScaleOutPolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AdjustmentType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ChangeInCapacity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ScalingAdjustment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CloudWatch Alarm for Scale-Out Command:&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 cloudwatch put-metric-alarm &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-name&lt;/span&gt; &lt;span class="s2"&gt;"HighCPUAlarm"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--metric-name&lt;/span&gt; CPUUtilization &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--namespace&lt;/span&gt; AWS/EC2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--statistic&lt;/span&gt; Average &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--period&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--threshold&lt;/span&gt; 70 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--comparison-operator&lt;/span&gt; GreaterThanThreshold &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--dimensions&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AutoScalingGroupName,Value&lt;span class="o"&gt;=&lt;/span&gt;MyWebAppASG &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--evaluation-periods&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-actions&lt;/span&gt; arn:aws:autoscaling:us-east-1:123456789012:scalingPolicy:abcdef12-3456-7890-abcd-ef1234567890:autoScalingGroupName/MyWebAppASG:policyName/ScaleOutPolicy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Pro Tip:&lt;/em&gt; In my deployment, fine-tuning these thresholds reduced response times by 30% during peak periods while cutting idle capacity costs by 40%.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Performance Tuning of Compute Services: Right-Sizing and Recommendations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A. Utilizing AWS Compute Optimizer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Command for recommendations of underutilized EC2 instances:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws compute-optimizer get-ec2-instance-recommendations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"instanceRecommendations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"instanceArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:ec2:us-east-1:123456789012:instance/i-0123456789abcdef0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"instanceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"t3.medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"finding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Overprovisioned"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"utilizationMetrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"cpuUtilizationPercentage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;12.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"memoryUtilizationPercentage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;35.0&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"recommendationOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"instanceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"t3.small"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"projectedUtilizationMetrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"cpuUtilizationPercentage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"memoryUtilizationPercentage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;40.0&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"performanceRisk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LOW"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Pro Tip:&lt;/em&gt; Based on these recommendations, we can resize non-critical instances from &lt;strong&gt;t3.medium&lt;/strong&gt; to &lt;strong&gt;t3.small&lt;/strong&gt;, resulting in a 25% reduction in compute costs without compromising performance!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Custom CloudWatch Metrics for Application Performance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Monitoring application metrics to further optimize performance. &lt;br&gt;
For example, setting an alarm on request latency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudwatch put-metric-alarm &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-name&lt;/span&gt; &lt;span class="s2"&gt;"HighLatencyAlarm"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--metric-name&lt;/span&gt; RequestLatency &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--namespace&lt;/span&gt; &lt;span class="s2"&gt;"MyApp"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--statistic&lt;/span&gt; Average &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--period&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--threshold&lt;/span&gt; 200 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--comparison-operator&lt;/span&gt; GreaterThanThreshold &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--evaluation-periods&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-actions&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:sns:us-east-1:123456789012:NotifyMe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Suggestion:&lt;/em&gt; For many web applications, an average latency threshold of &lt;strong&gt;200ms&lt;/strong&gt; over a 5‑minute period is a sign of degrading performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Cost Optimization: Leveraging AWS Cost Explorer and Reserved/Spot Instances
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A. Querying Monthly Cost Data with AWS Cost Explorer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieve detailed cost data to gain insights into spending patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ce get-cost-and-usage &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--time-period&lt;/span&gt; &lt;span class="nv"&gt;Start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2025-01-01,End&lt;span class="o"&gt;=&lt;/span&gt;2025-01-31 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--granularity&lt;/span&gt; MONTHLY &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--metrics&lt;/span&gt; &lt;span class="s2"&gt;"UnblendedCost"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ResultsByTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"TimePeriod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-01-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"End"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-01-31"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"UnblendedCost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1500.00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Groups"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Estimated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;B. Combining Compute Optimizer with Reserved/Spot Instances&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Based on the cost analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can convert underutilized on-demand instances to &lt;strong&gt;Reserved Instances&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Spot Instances&lt;/strong&gt; for stateless or non-critical workloads.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-reserved-instances &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;state,Values&lt;span class="o"&gt;=&lt;/span&gt;active
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Pro Insight:&lt;/em&gt;&lt;br&gt;&lt;br&gt;
By shifting from on-demand to reserved instances for predictable workloads and leveraging spot instances for batch processing, my env. achieved a 20% overall cost reduction over three months.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Measurable Business Impact
&lt;/h2&gt;

&lt;p&gt;Integrating these strategies resulted in significant improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto Scaling:&lt;/strong&gt; Reduced average CPU utilization from 85% to 55% during peak hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right-Sizing:&lt;/strong&gt; Achieved a 25% reduction in compute costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Optimization:&lt;/strong&gt; Realized a 20% reduction in monthly expenses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Improvement:&lt;/strong&gt; Lowered response times by approximately 30%, enhancing overall user experience.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Conclusion
&lt;/h2&gt;

&lt;p&gt;Optimizing performance and cost on AWS requires a comprehensive approach that combines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Auto Scaling:&lt;/strong&gt; Setting precise thresholds (70% for scale-out, 30% for scale-in) to efficiently match capacity with demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Tuning:&lt;/strong&gt; We can utilize AWS Compute Optimizer and custom CloudWatch metrics for right-sizing instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Management:&lt;/strong&gt; We can use insights from AWS Cost Explorer in combination with reserved and spot instance strategies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By continuously monitoring and refining these parameters, we can achieve tangible improvements in our AWS deployments.&lt;/p&gt;

&lt;p&gt;Happy optimizing! :)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>performance</category>
      <category>cost</category>
      <category>optimization</category>
    </item>
    <item>
      <title>Securing AWS Environments with Advanced IAM &amp; Zero Trust</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Fri, 07 Feb 2025 10:00:00 +0000</pubDate>
      <link>https://dev.to/prakash_rao/securing-aws-environments-with-advanced-iam-zero-trust-a-hands-on-approach-59ab</link>
      <guid>https://dev.to/prakash_rao/securing-aws-environments-with-advanced-iam-zero-trust-a-hands-on-approach-59ab</guid>
      <description>&lt;p&gt;In an era where cloud security is of utmost importance, implementing a &lt;code&gt;zero-trust model&lt;/code&gt; is essential. Zero trust means that no user or resource is trusted by default—even those within your network. In this post, I’ll demonstrate how to architect a secure AWS environment by using advanced IAM policies, AWS Organization's SCPs, and AWS Security Hub for continuous monitoring and risk mitigation. This guide includes practical CLI commands, sample outputs, and a real-world case study to illustrate the impact on security posture.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Note:&lt;/code&gt; All commands assume that you have the AWS CLI configured with the necessary permissions and that you’re operating in a test or development environment before applying changes in 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.amazonaws.com%2Fuploads%2Farticles%2Fm4icvaa7zf4cv3sbv2ww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4icvaa7zf4cv3sbv2ww.png" alt="Zero Trust" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Zero Trust and AWS
&lt;/h2&gt;

&lt;p&gt;A zero-trust security model requires verification for every access request—whether the request originates from inside or outside our network. In AWS, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strict Identity Verification: Using advanced IAM policies to enforce least privilege and role-based access.&lt;/li&gt;
&lt;li&gt;Boundary Enforcement: Using AWS Organizations and SCPs to control what actions can be performed across multiple AWS accounts.&lt;/li&gt;
&lt;li&gt;Continuous Monitoring: Leveraging AWS Security Hub to detect, report, and remediate any deviation from security best practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Advanced IAM Policies for Least Privilege
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A. Creating a Restrictive IAM Policy&lt;/strong&gt;&lt;br&gt;
One of the core elements of zero trust is ensuring that every IAM user, role, or service only has permissions necessary for their job functions. Here’s an example of an advanced IAM policy that grants read-only access to S3 buckets and CloudWatch logs—but nothing else.&lt;/p&gt;

&lt;p&gt;IAM Policy JSON (&lt;code&gt;ReadOnlyPolicy.json&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowReadOnlyS3",
      "Effect": "Allow",
      "Action": [
        "s3:Get*",
        "s3:List*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AllowReadOnlyCloudWatch",
      "Effect": "Allow",
      "Action": [
        "logs:Describe*",
        "logs:Get*",
        "logs:List*"
      ],
      "Resource": "*"
    }
  ]
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;B. Applying the Policy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Creating the policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws iam create-policy --policy-name ReadOnlyPolicy --policy-document file://ReadOnlyPolicy.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Policy": {
    "PolicyName": "ReadOnlyPolicy",
    "PolicyId": "ABCDEFGHIJKLMN123456",
    "Arn": "arn:aws:iam::123456789012:policy/ReadOnlyPolicy",
    "Path": "/",
    "DefaultVersionId": "v1",
    "AttachmentCount": 0,
    "PermissionsBoundaryUsageCount": 0,
    "IsAttachable": true,
    "CreateDate": "2025-01-15T12:00:00Z",
    "UpdateDate": "2025-01-15T12:00:00Z"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Best Practice:&lt;/code&gt; We need to ensure every user or role is attached only to the policies that they require. And also we need to combine this with permission boundaries when delegating administration.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Enforcing Boundaries with AWS Organizations and SCPs
&lt;/h2&gt;

&lt;p&gt;AWS Organizations allows us to centrally manage multiple AWS accounts. By applying SCPs, we can enforce security boundaries across all accounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Example SCP for Zero Trust&lt;/strong&gt;&lt;br&gt;
Here’s an SCP that denies the use of risky actions (for example, IAM policy modifications) unless explicitly allowed. Let's save this SCP as &lt;code&gt;ZeroTrustSCP.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyNonApprovedIAMChanges",
      "Effect": "Deny",
      "Action": [
        "iam:CreatePolicy",
        "iam:DeletePolicy",
        "iam:AttachUserPolicy",
        "iam:DetachUserPolicy",
        "iam:AttachRolePolicy",
        "iam:DetachRolePolicy"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalTag/ApprovedForIAMChanges": "true"
        }
      }
    }
  ]
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;B. Attaching the SCP via CLI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say we have an Organizational Unit (OU) with ID ou-1234-abcdef, for attaching the SCP:&lt;/p&gt;

&lt;p&gt;Create Policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws organizations create-policy \
  --name "ZeroTrustSCP" \
  --description "Deny risky IAM changes unless approved" \
  --type SERVICE_CONTROL_POLICY \
  --content file://ZeroTrustSCP.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Policy": {
    "PolicySummary": {
      "Id": "p-0123456789abcdef",
      "Arn": "arn:aws:organizations::123456789012:policy/o-exampleorgid/p-0123456789abcdef",
      "Name": "ZeroTrustSCP",
      "Description": "Deny risky IAM changes unless approved",
      "Type": "SERVICE_CONTROL_POLICY",
      "AwsManaged": false
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then attach the SCP to the OU:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws organizations attach-policy --policy-id p-0123456789abcdef --target-id ou-1234-abcdef
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Best Practice:&lt;/code&gt; We need to regularly review and update SCPs to reflect evolving security requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Continuous Monitoring with AWS Security Hub
&lt;/h2&gt;

&lt;p&gt;AWS Security Hub aggregates security findings from various AWS services and partner tools, offering a centralized view of our security posture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Enabling Security Hub&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws securityhub enable-security-hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "SecurityHubArn": "arn:aws:securityhub:us-east-1:123456789012:hub/default"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;B. Custom Insights for Zero Trust&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can create a custom insight to monitor for any IAM policy changes that fall outside your defined boundaries. For example, track any unauthorized IAM policy attachments.&lt;/p&gt;

&lt;p&gt;Create an Insight (using JSON conf.):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Name": "UnauthorizedIAMPolicyChanges",
  "Filters": {
    "ResourceType": [
      {
        "Value": "AwsIamPolicy",
        "Comparison": "EQUALS"
      }
    ],
    "ComplianceStatus": [
      {
        "Value": "FAILED",
        "Comparison": "EQUALS"
      }
    ]
  },
  "GroupByAttribute": "ResourceId"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command to create the insight:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws securityhub create-insight --cli-input-json file://UnauthorizedIAMPolicyChanges.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Best Practice:&lt;/code&gt; Integrate Security Hub with AWS Config and CloudWatch Events for real-time alerting and automated remediation.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Case Study: Zero Trust Implementation in a Multi-Account Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say our organization manages a multi-account AWS environment through AWS Organizations. A misconfigured IAM policy in one of the development accounts resulted in overly permissive access, potentially exposing sensitive data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remediation Steps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Advanced IAM Policies:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;a. We immediately reviewed all IAM policies and enforced our custom read-only policy.&lt;br&gt;
b. Applied permission boundaries to prevent escalation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;SCP Enforcement:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;a. Our ZeroTrustSCP automatically denied risky IAM changes from users lacking the “ApprovedForIAMChanges” tag.&lt;br&gt;
b. We quickly identified and revoked unauthorized policy attachments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continuous Monitoring:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;a. AWS Security Hub flagged the non-compliant IAM activity through our custom insight.&lt;br&gt;
b. Automated CloudWatch Events triggered remediation scripts to alert security personnel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The implementation of these measures reduced the risk exposure significantly. The zero-trust model ensured that even if an account was compromised, the enforced boundaries prevented lateral movement and unauthorized changes. Regular audits and automated monitoring continue to enhance our security posture.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Conclusion
&lt;/h2&gt;

&lt;p&gt;Implementing a zero-trust security model in AWS is not a one-time task but a continuous process. By combining advanced IAM policies, enforcing boundaries through AWS Organizations’ SCPs, and continuously monitoring with AWS Security Hub, we can create a robust security framework that mitigates risk and strengthens our cloud deployments.&lt;/p&gt;

&lt;p&gt;Feel free to share your questions or insights in the comments below. &lt;/p&gt;

&lt;p&gt;Happy Securing ;)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>iam</category>
      <category>cloud</category>
    </item>
    <item>
      <title>IaC Deep Dive: CloudFormation vs Terraform</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Wed, 05 Feb 2025 10:00:00 +0000</pubDate>
      <link>https://dev.to/prakash_rao/iac-deep-dive-cloudformation-vs-terraform-3bli</link>
      <guid>https://dev.to/prakash_rao/iac-deep-dive-cloudformation-vs-terraform-3bli</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopfor60nkt36duwcx3o1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopfor60nkt36duwcx3o1.png" alt="Comparison" width="800" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In today’s enterprise IT landscape, Infrastructure as Code (IaC) is a critical component for automating deployments, managing environments, and ensuring reliability. In this post, I’ll compare two popular IaC tools—AWS CloudFormation and Terraform. By exploring real-world scenarios, code examples, best practices, and challenges in multi-environment deployments. The goal is to demonstrate how a well-architected IaC approach can speed up deployments and improve overall reliability.&lt;/p&gt;

&lt;p&gt;Prerequisites: Make sure that AWS CLI, Terraform is installed and configured with appropriate permissions.&lt;br&gt;
Note: All flowcharts are made with mermaid.live&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;IaC enables us to manage our Infra through code rather than manual processes. In enterprises with multiple environments (dev, staging, prod), consistency, version control, and repeatability are essential. CloudFormation is AWS-native and tightly integrated with AWS services, while Terraform offers a multi-cloud approach with a rich plugin ecosystem. In this deep dive, we will see both tools side-by-side.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Real-World Scenario: Multi-Env. Deployments
&lt;/h2&gt;

&lt;p&gt;Imagine we need to deploy a common set of resources (e.g., an S3 bucket, an IAM role, and a Lambda function) across multiple environments.&lt;/p&gt;

&lt;p&gt;Key requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistency: All environments must have identical infrastructure configurations.&lt;/li&gt;
&lt;li&gt;Versioning: Infrastructure definitions should be version-controlled.&lt;/li&gt;
&lt;li&gt;Automation: Deployments must be repeatable and automated.&lt;/li&gt;
&lt;li&gt;Flexibility: Ability to customize settings per environment (e.g., bucket naming, logging).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  3. AWS CloudFormation Deep Dive
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgcl9nqtgyebdthcvb6y9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgcl9nqtgyebdthcvb6y9.png" alt="CF deepdive" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Sample CloudFormation Template&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is a simple CloudFormation YAML template that creates an S3 bucket with a parameterized name. Let's save this as &lt;code&gt;cf-s3-bucket.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWSTemplateFormatVersion: '2010-09-09'
Description: &amp;gt;
  CloudFormation template for creating an S3 bucket with environment-specific naming.

Parameters:
  Environment:
    Type: String
    Description: "Deployment environment (dev, staging, prod)"
    AllowedValues:
      - dev
      - staging
      - prod

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "myapp-${Environment}-bucket"
      VersioningConfiguration:
        Status: Enabled

Outputs:
  BucketName:
    Description: "Name of the created S3 bucket"
    Value: !Ref S3Bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;B. Deploying with CloudFormation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's use the AWS CLI to deploy the stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws cloudformation deploy \
  --template-file cf-s3-bucket.yml \
  --stack-name MyApp-S3-Stack \
  --parameter-overrides Environment=dev \
  --capabilities IAM_CAPABILITY_NAME
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/MyApp-S3-Stack/abcdef12-3456-7890-abcd-ef1234567890"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deployment, we can verify the bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws cloudformation describe-stacks --stack-name MyApp-S3-Stack \
  --query "Stacks[0].Outputs[?OutputKey=='BucketName'].OutputValue" --output text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myapp-dev-bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C. Best Practices &amp;amp; Challenges with CloudFormation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modular Templates: Use nested stacks or include statements for large infrastructures.&lt;/li&gt;
&lt;li&gt;Change Sets: Always review change sets before applying updates to prod.&lt;/li&gt;
&lt;li&gt;Template Validation: Use aws &lt;code&gt;cloudformation validate-template&lt;/code&gt; to catch errors early.&lt;/li&gt;
&lt;li&gt;Limitations: CloudFormation can be verbose sometimes, and managing the drift across environments is challenging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Terraform Deep Dive
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek8837hdz9sax3yrx3bb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek8837hdz9sax3yrx3bb.png" alt="Terraform Deepdive" width="800" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Sample Terraform Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is a Terraform configuration that creates an S3 bucket similar to our CloudFormation example. Let's save this as &lt;code&gt;main.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "us-east-1"
}

variable "environment" {
  description = "Deployment environment (dev, staging, prod)"
  type        = string
  default     = "dev"
}

resource "aws_s3_bucket" "myapp_bucket" {
  bucket = "myapp-${var.environment}-bucket"
  versioning {
    enabled = true
  }
}

output "bucket_name" {
  value = aws_s3_bucket.myapp_bucket.bucket
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;B. Deploying with Terraform&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initialize Terraform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!

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

&lt;/div&gt;



&lt;p&gt;Plan the Deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform plan -var="environment=dev"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:
  + aws_s3_bucket.myapp_bucket
      bucket: "myapp-dev-bucket"
Plan: 1 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the Configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply -var="environment=dev" --auto-approve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws_s3_bucket.myapp_bucket: Creating...
aws_s3_bucket.myapp_bucket: Creation complete after 3s [id=myapp-dev-bucket]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:
bucket_name = "myapp-dev-bucket"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  C. Best Practices &amp;amp; Challenges with Terraform
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;State Management: Use remote state backends (e.g., S3 with DynamoDB locking) to manage state in multi-environment deployments.&lt;/li&gt;
&lt;li&gt;Workspaces: Leverage Terraform workspaces to isolate environments (e.g., dev, staging, prod).&lt;/li&gt;
&lt;li&gt;Modularization: Break your configurations into reusable modules for maintainability.&lt;/li&gt;
&lt;li&gt;Challenges: Handling state drift and managing state file locks in concurrent deployments can be complex.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. CloudFormation vs. Terraform
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;CloudFormation&lt;/th&gt;
      &lt;th&gt;Terraform&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    
    &lt;tr&gt;
      
      &lt;td rowspan="3"&gt;Pros&lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;AWS-Native:&lt;/strong&gt; Tight integration with AWS services and IAM.
      &lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;Multi-Cloud Support:&lt;/strong&gt; Manage infrastructure across AWS, Azure, GCP, and more. So Developer can get familiar with code easily with cloud-switching.
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;strong&gt;No Additional Installation:&lt;/strong&gt; Managed directly via AWS.
      &lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;Modularity:&lt;/strong&gt; Rich ecosystem of modules and providers.
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;strong&gt;Drift Detection:&lt;/strong&gt; Built-in drift detection for resources.
      &lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;Plan &amp;amp; Apply Workflow:&lt;/strong&gt; Clear visibility of changes before deployment.
      &lt;/td&gt;
    &lt;/tr&gt;
    
    
    &lt;tr&gt;
      
      &lt;td rowspan="2"&gt;Cons&lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;Verbosity:&lt;/strong&gt; Templates can become lengthy and difficult to maintain.
      &lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;State Management:&lt;/strong&gt; Requires careful handling of state files, especially in team environments.
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;strong&gt;AWS-Only:&lt;/strong&gt; Limited to AWS environments.
      &lt;/td&gt;
      &lt;td&gt;
        &lt;strong&gt;Learning Curve:&lt;/strong&gt; HCL and Terraform’s workflow can be complex for newcomers.
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  6. Best Practices for Multi-Env. Deployments
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Parameterization &amp;amp; Variables: Both tools support parameterization—use variables (Terraform) or parameters (CloudFormation) to adapt resources per environment.&lt;/li&gt;
&lt;li&gt;Modularization: Breaking down of infrastructure into smaller, reusable components is beneficial.&lt;/li&gt;
&lt;li&gt;Version Control: Store our IaC code in a version-controlled repository.&lt;/li&gt;
&lt;li&gt;Automated Testing: Integrating with CI/CD pipelines to validate the Infra changes.&lt;/li&gt;
&lt;li&gt;Documentation: Maintaining clear documentation of modules, parameters, and expected outputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Important Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Drift Management: In CloudFormation, resource drift can lead to inconsistencies so regular audits and change sets are critical. In Terraform, we need to ensure robust state locking and frequent state refreshes.&lt;/li&gt;
&lt;li&gt;Complex Dependencies: Managing interdependent resources across environments requires careful planning and modular design.&lt;/li&gt;
&lt;li&gt;Rollback Strategies: Design your stacks and modules to support smooth rollbacks in case of failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Conclusion
&lt;/h2&gt;

&lt;p&gt;Both AWS CloudFormation and Terraform offer good solutions for managing infrastructure as code in complex, multi-env deployments. While CloudFormation provides deep integration with AWS, Terraform’s flexibility across multiple clouds can be a significant advantage for developers. By implementing best practices such as modularization, automated testing, and effective state management, we can achieve faster deployments and improved reliability.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudformation</category>
      <category>terraform</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Architecting Advanced CI/CD pipelines in AWS</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Tue, 04 Feb 2025 01:44:02 +0000</pubDate>
      <link>https://dev.to/prakash_rao/architecting-advanced-cicd-pipelines-in-aws-24bc</link>
      <guid>https://dev.to/prakash_rao/architecting-advanced-cicd-pipelines-in-aws-24bc</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/prakash_rao/advanced-cicd-pipelines-on-aws-30ch" class="crayons-story__hidden-navigation-link"&gt;Advanced CI/CD Pipelines on AWS&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/prakash_rao" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F1595996%2Fc8b3c865-cb83-4f58-80ad-8e973a535876.jpg" alt="prakash_rao profile" class="crayons-avatar__image" width="800" height="739"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/prakash_rao" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Prakash Rao
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Prakash Rao
                
                
              
              &lt;div id="story-author-preview-content-2255005" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/prakash_rao" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F1595996%2Fc8b3c865-cb83-4f58-80ad-8e973a535876.jpg" class="crayons-avatar__image" alt="" width="800" height="739"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Prakash Rao&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/prakash_rao/advanced-cicd-pipelines-on-aws-30ch" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 3 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/prakash_rao/advanced-cicd-pipelines-on-aws-30ch" id="article-link-2255005"&gt;
          Advanced CI/CD Pipelines on AWS
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cicd"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cicd&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cloud"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cloud&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/prakash_rao/advanced-cicd-pipelines-on-aws-30ch" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;7&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/prakash_rao/advanced-cicd-pipelines-on-aws-30ch#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>aws</category>
      <category>cicd</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Advanced CI/CD Pipelines on AWS</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Mon, 03 Feb 2025 10:00:00 +0000</pubDate>
      <link>https://dev.to/prakash_rao/advanced-cicd-pipelines-on-aws-30ch</link>
      <guid>https://dev.to/prakash_rao/advanced-cicd-pipelines-on-aws-30ch</guid>
      <description>&lt;p&gt;In this post, I’ll walk you through setting up an advanced CI/CD pipeline on AWS using native services and show you how to create and configure components like CodeBuild, CodeDeploy, and CodePipeline using AWS CLI commands and configuration files. I will also include outputs for each command so you can see what to expect when you run these commands yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lmdx23dlin6nud8j1mk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lmdx23dlin6nud8j1mk.png" alt="Flow Chart" width="744" height="1458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Flowchart was created using mermaid.live&lt;/li&gt;
&lt;li&gt;Since CodeCommit is no longer onboarding new customers, choosing GitHub as the source repository. If you already have a GitHub repository for your project, simply update the configuration files accordingly.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Prerequisites: Please make sure that the AWS CLI is installed and configured with the proper IAM permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create a Source Repository in GitHub
&lt;/h2&gt;

&lt;p&gt;First, let’s create a new GitHub repository where our source code will be there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
git remote add origin https://github.com/&amp;lt;YOUR_GITHUB_USERNAME&amp;gt;/advanced-ci-cd-repo.git
git add .
git commit -m "Initial commit"
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Set Up a CodeBuild Project
&lt;/h2&gt;

&lt;p&gt;Next let's create a CodeBuild project that builds our application. In this example, we’ll use a simple Node.js project. Save the following JSON configuration as &lt;code&gt;codebuild-project.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "advanced-ci-cd-build",
  "description": "Build project for advanced CI/CD pipeline demo",
  "source": {
    "type": "GITHUB",
    "location": "https://github.com/&amp;lt;YOUR_GITHUB_USERNAME&amp;gt;/advanced-ci-cd-repo"
  },
  "artifacts": {
    "type": "NO_ARTIFACTS"
  },
  "environment": {
    "type": "LINUX_CONTAINER",
    "image": "aws/codebuild/standard:6.0",
    "computeType": "BUILD_GENERAL1_MEDIUM",
    "environmentVariables": [
      {
        "name": "NODE_ENV",
        "value": "production"
      }
    ]
  },
  "serviceRole": "arn:aws:iam::&amp;lt;YOUR_ACCOUNT_ID&amp;gt;:role/CodeBuildServiceRole"
}

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

&lt;/div&gt;



&lt;p&gt;Create project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws codebuild create-project --cli-input-json file://codebuild-project.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "project": {
    "name": "advanced-ci-cd-build",
    "arn": "arn:aws:codebuild:us-east-1:123456789012:project/advanced-ci-cd-build",
    "description": "Build project for advanced CI/CD pipeline demo",
    "source": {
      "type": "GITHUB",
      "location": "https://github.com/&amp;lt;YOUR_GITHUB_USERNAME&amp;gt;/advanced-ci-cd-repo"
    },
    "artifacts": {
      "type": "NO_ARTIFACTS"
    },
    "environment": {
      "type": "LINUX_CONTAINER",
      "image": "aws/codebuild/standard:6.0",
      "computeType": "BUILD_GENERAL1_MEDIUM",
      "environmentVariables": [
        {
          "name": "NODE_ENV",
          "value": "production"
        }
      ]
    },
    "serviceRole": "arn:aws:iam::&amp;lt;YOUR_ACCOUNT_ID&amp;gt;:role/CodeBuildServiceRole",
    "created": "2024-05-10T15:00:00Z"
  }
}

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

&lt;/div&gt;



&lt;p&gt;Note: Make sure CodeBuild service role has permissions for GitHub, S3 (if you use artifacts), and CloudWatch logging.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Define a Build Specification (&lt;code&gt;buildspec.yml&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;buildspec.yml&lt;/code&gt; file in the root of the repository. This file instructs CodeBuild on how to run our build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 16
    commands:
      - echo "Installing dependencies..."
      - npm install
  pre_build:
    commands:
      - echo "Running lint and tests..."
      - npm run lint
      - npm test
  build:
    commands:
      - echo "Building the project..."
      - npm run build
  post_build:
    commands:
      - echo "Build completed on `date`"
artifacts:
  files:
    - '**/*'
  discard-paths: yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push this file to the GitHub repository so CodeBuild uses it during the build process.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Set Up a CodeDeploy Application and Deployment Group
&lt;/h2&gt;

&lt;p&gt;For blue/green deployments, we’ll use CodeDeploy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a CodeDeploy Application&lt;/strong&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws deploy create-application \
    --application-name advanced-ci-cd-app \
    --compute-platform Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "applicationId": "abcdef12-3456-7890-abcd-ef1234567890",
  "applicationName": "advanced-ci-cd-app",
  "computePlatform": "Server"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create a Deployment Group&lt;/strong&gt;&lt;br&gt;
Save the following as &lt;code&gt;deployment-group.json&lt;/code&gt; (update below values as needed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "applicationName": "advanced-ci-cd-app",
  "deploymentGroupName": "advanced-ci-cd-deploy-group",
  "deploymentConfigName": "CodeDeployDefault.OneAtATime",
  "ec2TagFilters": [
    {
      "Key": "Name",
      "Value": "MyAppServer",
      "Type": "KEY_AND_VALUE"
    }
  ],
  "serviceRoleArn": "arn:aws:iam::&amp;lt;YOUR_ACCOUNT_ID&amp;gt;:role/CodeDeployServiceRole",
  "blueGreenDeploymentConfiguration": {
    "terminateBlueInstancesOnDeploymentSuccess": {
      "action": "TERMINATE",
      "terminationWaitTimeInMinutes": 5
    },
    "deploymentReadyOption": {
      "actionOnTimeout": "CONTINUE_DEPLOYMENT"
    }
  },
  "autoRollbackConfiguration": {
    "enabled": true,
    "events": ["DEPLOYMENT_FAILURE"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create Deployment group with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws deploy create-deployment-group --cli-input-json file://deployment-group.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "deploymentGroupId": "abcdef12-3456-7890-abcd-ef1234567890",
  "deploymentGroupName": "advanced-ci-cd-deploy-group",
  "applicationName": "advanced-ci-cd-app"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: Make sure that the CodeDeploy service role has the necessary permissions to access EC2 and execute deployment actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Create a CodePipeline
&lt;/h2&gt;

&lt;p&gt;Let's put everything together by creating a pipeline that orchestrates the source, build, and deployment stages.&lt;/p&gt;

&lt;p&gt;Save the following as &lt;code&gt;pipeline.json&lt;/code&gt; (adjust names, regions, and bucket names as needed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "pipeline": {
    "name": "advanced-ci-cd-pipeline",
    "roleArn": "arn:aws:iam::&amp;lt;YOUR_ACCOUNT_ID&amp;gt;:role/CodePipelineServiceRole",
    "artifactStore": {
      "type": "S3",
      "location": "&amp;lt;YOUR_ARTIFACT_BUCKET&amp;gt;"
    },
    "stages": [
      {
        "name": "Source",
        "actions": [
          {
            "name": "SourceAction",
            "actionTypeId": {
              "category": "Source",
              "owner": "ThirdParty",
              "provider": "GitHub",
              "version": "1"
            },
            "outputArtifacts": [
              {
                "name": "SourceOutput"
              }
            ],
            "configuration": {
              "Owner": "&amp;lt;YOUR_GITHUB_USERNAME&amp;gt;",
              "Repo": "advanced-ci-cd-repo",
              "Branch": "main",
              "OAuthToken": "&amp;lt;YOUR_GITHUB_OAUTH_TOKEN&amp;gt;"
            },
            "runOrder": 1
          }
        ]
      },
      {
        "name": "Build",
        "actions": [
          {
            "name": "BuildAction",
            "actionTypeId": {
              "category": "Build",
              "owner": "AWS",
              "provider": "CodeBuild",
              "version": "1"
            },
            "inputArtifacts": [
              {
                "name": "SourceOutput"
              }
            ],
            "outputArtifacts": [
              {
                "name": "BuildOutput"
              }
            ],
            "configuration": {
              "ProjectName": "advanced-ci-cd-build"
            },
            "runOrder": 1
          }
        ]
      },
      {
        "name": "Deploy",
        "actions": [
          {
            "name": "DeployAction",
            "actionTypeId": {
              "category": "Deploy",
              "owner": "AWS",
              "provider": "CodeDeploy",
              "version": "1"
            },
            "inputArtifacts": [
              {
                "name": "BuildOutput"
              }
            ],
            "configuration": {
              "ApplicationName": "advanced-ci-cd-app",
              "DeploymentGroupName": "advanced-ci-cd-deploy-group"
            },
            "runOrder": 1
          }
        ]
      }
    ],
    "version": 1
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create pipeline with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws codepipeline create-pipeline --cli-input-json file://pipeline.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "pipeline": {
    "name": "advanced-ci-cd-pipeline",
    "version": 1,
    "artifactStore": {
      "type": "S3",
      "location": "my-artifact-bucket"
    },
    "stages": [
      {
        "name": "Source",
        "actions": [ { ..... } ]
      },
      {
        "name": "Build",
        "actions": [ { ..... } ]
      },
      {
        "name": "Deploy",
        "actions": [ { ..... } ]
      }
    ]
  },
  "created": "2024-05-10T15:30:00Z"
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Testing and Monitoring the Pipeline
&lt;/h2&gt;

&lt;p&gt;After creating the pipeline, trigger a test execution by pushing a commit to your GitHub repository. Then, check the pipeline status with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws codepipeline get-pipeline-execution --pipeline-name advanced-ci-cd-pipeline --pipeline-execution-id &amp;lt;execution-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "pipelineExecution": {
    "pipelineName": "advanced-ci-cd-pipeline",
    "pipelineExecutionId": "12345678-1234-1234-1234-123456789012",
    "status": "Succeeded",
    "artifactRevisions": [ ..... ],
    "startTime": "2024-05-10T15:31:00Z",
    "lastUpdateTime": "2024-05-10T15:33:00Z"
  }
}

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

&lt;/div&gt;



&lt;p&gt;Additionally, we can set up CloudWatch dashboards and alarms to monitor key metrics such as build duration and deployment status.&lt;/p&gt;

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

&lt;p&gt;In this blog I demonstrated how we can build an advanced CI/CD pipeline on AWS using CLI commands and configuration files. By integrating GitHub, CodeBuild, CodeDeploy (with blue/green deployments), and CodePipeline, we created a fully automated workflow. &lt;/p&gt;

&lt;p&gt;Happy Deploying! :)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cicd</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building Serverless Applications with AWS Lambda and integrating with DynamoDB</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Sat, 01 Feb 2025 03:22:50 +0000</pubDate>
      <link>https://dev.to/prakash_rao/building-serverless-applications-with-aws-lambda-and-integrating-with-dynamodb-3fcn</link>
      <guid>https://dev.to/prakash_rao/building-serverless-applications-with-aws-lambda-and-integrating-with-dynamodb-3fcn</guid>
      <description>&lt;h2&gt;
  
  
  Agenda
&lt;/h2&gt;

&lt;p&gt;1.Introduction&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is serverless architecture?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.Setting Up the Project&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a Lambda function with AWS CLI.&lt;/li&gt;
&lt;li&gt;Creating an API Gateway to trigger Lambda.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3.Building the Application&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a simple RESTful API with AWS Lambda and API Gateway.&lt;/li&gt;
&lt;li&gt;Integrating the API with DynamoDB to store data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4.Testing the Application&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invoking the Lambda function using AWS CLI.&lt;/li&gt;
&lt;li&gt;Testing the API endpoint using Postman or Curl.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5.Deploying the Application&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying the API to a production stage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;6.Conclusion&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Summing up the steps and benefits of using AWS Lambda.&lt;/li&gt;
&lt;li&gt;Further enhancements and scalability options.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is serverless architecture?
&lt;/h2&gt;

&lt;p&gt;Serverless architecture is not something new and has gained massive popularity for its ability to simplify development, reduce operational costs, and increase scalability. AWS Lambda, Amazon’s serverless compute service, plays a central role in this movement. With AWS Lambda, developers can run their code in response to events without having to provision or manage servers, making it easier to focus on the logic rather than infrastructure. This guide will show you how to build a complete serverless application using AWS Lambda and other AWS services like API Gateway and DynamoDB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Project
&lt;/h2&gt;

&lt;p&gt;Step 1: Create a Lambda Function with AWS CLI&lt;br&gt;
Let's first create the Lambda function that will execute our serverless logic. Use the AWS CLI to create the Lambda function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws lambda create-function \
  --function-name MyLambdaFunction \
  --runtime python3.8 \
  --role arn:aws:iam::your-account-id:role/execution-role \
  --handler lambda_function.lambda_handler \
  --zip-file fileb://my-deployment-package.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the Lambda function is written in Python, and we’ll upload the code in a ZIP file. We need to ensure that the execution-role has the necessary permissions to execute the function.&lt;/p&gt;

&lt;p&gt;Step 2: Create an API Gateway to Trigger Lambda&lt;br&gt;
Next, let's set up an API Gateway to trigger our Lambda function when an HTTP request is made. We can create a REST API using the following AWS CLI command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws apigateway create-rest-api \
  --name "MyAPI" \
  --description "API for serverless Lambda" \
  --endpoint-configuration types=REGIONAL

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

&lt;/div&gt;



&lt;p&gt;Once the API is created, let's make a note of the API ID provided in the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Application
&lt;/h2&gt;

&lt;p&gt;Step 3: Create a Resource for the API&lt;br&gt;
Now, we need to create a resource, such as &lt;code&gt;/items&lt;/code&gt;, that will handle the HTTP request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API_ID=&amp;lt;api-id-which-we-got-earlier&amp;gt;
aws apigateway create-resource \
  --rest-api-id $API_ID \
  --parent-id $(aws apigateway get-resources --rest-api-id $API_ID --query 'items[0].id' --output text) \
  --path-part "items"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Define a POST Method for the Resource&lt;br&gt;
After creating the resource, let's define a POST method that will trigger our Lambda function when a request is made:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws apigateway put-method \
  --rest-api-id $API_ID \
  --resource-id &amp;lt;resource-id&amp;gt; \
  --http-method POST \
  --authorization-type NONE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's integrate the POST method with the Lambda function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws apigateway put-integration \
  --rest-api-id $API_ID \
  --resource-id &amp;lt;resource-id&amp;gt; \
  --http-method POST \
  --integration-http-method POST \
  --type AWS_PROXY \
  --uri arn:aws:apigateway:&amp;lt;region&amp;gt;:lambda:path/2015-03-31/functions/arn:aws:lambda:&amp;lt;region&amp;gt;:&amp;lt;account-id&amp;gt;:function:MyLambdaFunction/invocations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Set Up DynamoDB Integration&lt;br&gt;
Now to store incoming data in DynamoDB we need to create a DynamoDB table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws dynamodb create-table \
  --table-name MyTable \
  --attribute-definitions AttributeName=id,AttributeType=S AttributeName=name,AttributeType=S \
  --key-schema AttributeName=id,KeyType=HASH \
  --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, update the Lambda function code to interact with DynamoDB, adding items to the table. Afterward, update the Lambda function code using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws lambda update-function-code \
  --function-name MyLambdaFunction \
  --zip-file fileb://my-updated-deployment-package.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing the Application
&lt;/h2&gt;

&lt;p&gt;Step 6: Invoke the Lambda Function&lt;br&gt;
Once everything is set up, we can test the Lambda function directly using AWS CLI. For example, to add an item to DynamoDB, we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws lambda invoke \
  --function-name MyLambdaFunction \
  --payload '{"id": "123", "name": "Sample"}' \
  output.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 7: Test the API Endpoint&lt;br&gt;
Use Curl to test the API. For instance, we can test the &lt;code&gt;/items&lt;/code&gt; endpoint by sending a POST request with the relevant data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -d '{"id": "123", "name": "Sample"}' https://&amp;lt;api-id&amp;gt;.execute-api.&amp;lt;region&amp;gt;.amazonaws.com/dev/items
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying the Application
&lt;/h2&gt;

&lt;p&gt;Step 8: Deploy the API&lt;br&gt;
Once everything is locally tested, we can deploy the API to a production stage by following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws apigateway create-deployment \
  --rest-api-id $API_ID \
  --stage-name prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will deploy the API to the &lt;code&gt;prod&lt;/code&gt; stage, and we'll receive a public URL that we can use to interact with the Lambda function via the API.&lt;/p&gt;

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

&lt;p&gt;AWS Lambda allows us to build serverless applications that scale effortlessly, without the need to manage infrastructure. By using the AWS CLI, we streamlined the process of creating and managing Lambda functions, API Gateway resources, and integrating with DynamoDB. This approach makes it possible to quickly deploy a scalable and cost-effective application that responds to events in real time.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>cloudcomputing</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Building Your First AWS VPC with Public and Private Subnets</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Mon, 16 Sep 2024 16:50:43 +0000</pubDate>
      <link>https://dev.to/prakash_rao/building-your-first-aws-vpc-with-public-and-private-subnets-33jo</link>
      <guid>https://dev.to/prakash_rao/building-your-first-aws-vpc-with-public-and-private-subnets-33jo</guid>
      <description>&lt;p&gt;Welcome to a comprehensive guide on setting up a Virtual Private Cloud (VPC) with public and private subnets in AWS. This tutorial is designed for individuals looking to understand and implement the basic network architecture within AWS to support various applications securely and robustly.&lt;/p&gt;

&lt;p&gt;First things first, lets start with a brief introduction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a VPC?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Virtual Private Cloud (VPC) is a virtual network dedicated to your AWS account. It is logically isolated from other virtual networks in the AWS Cloud. Within a VPC, you can define your own IP address range, create subnets, configure route tables, and network gateways, providing flexibility as well as security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Public vs. Private Subnets&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Public Subnet:&lt;/strong&gt;&lt;br&gt;
These are subnets with a route to the Internet through an Internet Gateway (IGW), making them accessible from the Internet. They are typically used to host external-facing resources, like web servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Private Subnet:&lt;/strong&gt; &lt;br&gt;
These subnets do not have a direct route to the Internet and are used for backend systems that should not be directly accessed from the outside world.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Internet Gateway (IGW)&lt;/strong&gt;&lt;br&gt;
An Internet Gateway is a VPC component that allows communication between your VPC and the Internet. Attaching an IGW to VPC is essential for public subnet to communicate with the Internet.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will walk through the process of setting up this network structure using both the AWS Management Console and the AWS CLI. This dual approach helps illustrate the underlying processes and allows you to choose the method that best fits your working style.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using the AWS Management Console
&lt;/h2&gt;

&lt;p&gt;We'll start by demonstrating each step with the AWS Management Console, providing screenshots to guide you through each part of the process. This method is especially helpful for those who prefer a visual interface and are newer to AWS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First type VPC, in the search box and select it.&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.amazonaws.com%2Fuploads%2Farticles%2Fhyj0pdy0aw2nd4pxh1m9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyj0pdy0aw2nd4pxh1m9.png" alt=" " width="799" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;then select create VPC &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.amazonaws.com%2Fuploads%2Farticles%2Fy7hkp9a3b7302x5223w2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7hkp9a3b7302x5223w2.png" alt=" " width="800" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select VPC and more. Previously it used to be only VPC, but with this option we can create subnets, IGW within the same configuration&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.amazonaws.com%2Fuploads%2Farticles%2F34o8eeb29yoez8evpcg5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F34o8eeb29yoez8evpcg5.png" alt=" " width="799" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;choose a CIDR range&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ys57sxtuz2gs03sf062.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ys57sxtuz2gs03sf062.png" alt=" " width="800" height="663"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;choose no. of AZs, the public and private subnet changes automatically based on this but you can manually select as well.&lt;/p&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fu0f4zwml3krqn28yxa2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0f4zwml3krqn28yxa2x.png" alt=" " width="800" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the side preview you can see what resources are going to be created.&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.amazonaws.com%2Fuploads%2Farticles%2Fkme85sxbhquize4jejmf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkme85sxbhquize4jejmf.png" alt=" " width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leave the remaining options default and select "create VPC" button  at the bottom&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.amazonaws.com%2Fuploads%2Farticles%2Fwjq7xu56c4fuzm34q8l6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwjq7xu56c4fuzm34q8l6.png" alt=" " width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It will start creating the resources based on selection&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxdpr7hhas06twr52w9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxdpr7hhas06twr52w9e.png" alt=" " width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;after few seconds, your VPC will be created.&lt;/p&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fnywc3xpxau5ssj24vhg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnywc3xpxau5ssj24vhg1.png" alt=" " width="800" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After you select the view VPC, you can see the resource map &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.amazonaws.com%2Fuploads%2Farticles%2Fj4owgerk7tan3yerrj4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4owgerk7tan3yerrj4q.png" alt=" " width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Using the AWS CLI
&lt;/h2&gt;

&lt;p&gt;Following that, we will replicate the setup using the AWS CLI, which is ideal for those who prefer script-based configurations or need to automate their setup processes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the VPC
First, create a VPC with a 10.1.0.0/16 CIDR block:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 create-vpc --cidr-block 10.1.0.0/16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command returns a VPC ID, which we will use in subsequent steps. Let's assume it returns vpc-0a1b2c3d4e5f67890.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the Subnets
Next, create the public and private subnets within this VPC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Public Subnet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 create-subnet --vpc-id vpc-0a1b2c3d4e5f67890 --cidr-block 10.1.1.0/24 --availability-zone us-east-1a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command returns a Subnet ID for the public subnet, assume it’s subnet-1234567890abcdef0.&lt;/p&gt;

&lt;p&gt;Private Subnet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 create-subnet --vpc-id vpc-0a1b2c3d4e5f67890 --cidr-block 10.1.2.0/24 --availability-zone us-east-1a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assume the returned Subnet ID for the private subnet is subnet-0987654321fedcba0.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an Internet Gateway
Create an Internet Gateway and attach it to your VPC:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 create-internet-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command returns an Internet Gateway ID, let's say it's igw-0123456789abcdef0.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach the Internet Gateway to the VPC:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 attach-internet-gateway --vpc-id vpc-0a1b2c3d4e5f67890 --internet-gateway-id igw-0123456789abcdef0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Configure Route Tables
Create a route table for the public subnet and configure it to route traffic to the Internet Gateway.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 create-route-table --vpc-id vpc-0a1b2c3d4e5f67890

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

&lt;/div&gt;



&lt;p&gt;Assume the returned Route Table ID is rtb-02468acefdb97531.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create Route to Internet Gateway:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 create-route --route-table-id rtb-02468acefdb97531 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-0123456789abcdef0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Associate the Route Table with the Public Subnet:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 associate-route-table --subnet-id subnet-1234567890abcdef0 --route-table-id rtb-02468acefdb97531
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the private subnet, we do not need to route traffic to the Internet Gateway, but we may want to create a separate route table if required for specific network rules or future modifications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
These CLI commands and console process will create a VPC with a public and private subnet setup, where the public subnet has internet access via an Internet Gateway. This setup is fundamental for many applications and services hosted on AWS.&lt;br&gt;
This post will be extremely beneficial for those new to AWS and those needing a refresher on setting up a VPC properly :) &lt;/p&gt;

</description>
    </item>
    <item>
      <title>SAP NetWeaver Migration from On-Prem to AWS</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Sat, 31 Aug 2024 16:24:13 +0000</pubDate>
      <link>https://dev.to/prakash_rao/sap-netweaver-migration-from-on-prem-to-aws-g1b</link>
      <guid>https://dev.to/prakash_rao/sap-netweaver-migration-from-on-prem-to-aws-g1b</guid>
      <description>&lt;p&gt;This post provides the necessary documentation for migrating a simulated deployment of SAP NetWeaver OnPrem (simulated) to a different AWS environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vgjreju5g617vpbxr7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vgjreju5g617vpbxr7o.png" alt="sap" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The migration process involves the following high-level steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Launch an EC2 instance and install SAP NetWeaver on it.&lt;/li&gt;
&lt;li&gt;Create a simulation as in on-prem, the SAP NetWeaver deployment in the AWS environment.&lt;/li&gt;
&lt;li&gt;Convert the EC2 instance into an OVA file and store it in Amazon S3.&lt;/li&gt;
&lt;li&gt;Create an Amazon Machine Image (AMI) and EBS snapshot.&lt;/li&gt;
&lt;li&gt;Launch a new EC2 instance from the AMI and EBS snapshot in the new AWS environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you can begin the migration process, you will need to have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with sufficient privileges to create and manage the necessary resources.&lt;/li&gt;
&lt;li&gt;Access to the AWS Management Console and AWS CLI.&lt;/li&gt;
&lt;li&gt;Familiarity with AWS services and concepts such as EC2, S3, and VPC.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migration Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1,2: Launch an EC2 instance and install SAP NetWeaver on it
&lt;/h3&gt;

&lt;p&gt;Launch an EC2 instance in the AWS environment and install SAP NetWeaver on it. Ensure that the instance is properly configured and that SAP NetWeaver is running correctly.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226990388-5b6efaee-7709-4275-8725-18a54bfef55e.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_22-03-37_1" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226990388-5b6efaee-7709-4275-8725-18a54bfef55e.png" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989804-964111b6-2b1a-40d4-93eb-3ed12f8b78fe.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_22-07-22" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989804-964111b6-2b1a-40d4-93eb-3ed12f8b78fe.png" height="764"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989807-65ce330c-d258-4552-8400-09a3019adcfc.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-22_22-10-07" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989807-65ce330c-d258-4552-8400-09a3019adcfc.png" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's install the necessary packages require for the SAP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install libaio1
sudo apt-get install csh
sudo apt install libc6
sudo apt-get install uuid
sudo service uuidd start
sudo update-locale LANG=”en_US.UTF-8"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For setting up VNC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade
sudo sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
sudo /etc/init.d/ssh restart
sudo passwd ubuntu
sudo apt install xrdp xfce4 xfce4-goodies tightvncserver
echo xfce4-session&amp;gt; /home/ubuntu/.xsession
sudo cp /home/ubuntu/.xsession /etc/skel
sudo sed -i '0,/-1/s//ask-1/' /etc/xrdp/xrdp.ini
sudo service xrdp restart
tightvncserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For downloading the SAP netweaver let's install firefox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo add-apt-repository ppa:ubuntu-mozilla-security/ppa
sudo apt-get update
sudo apt-get install firefox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989811-7f6426ac-9cd9-4665-aba9-bfab87eea4c8.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_22-12-43" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989811-7f6426ac-9cd9-4665-aba9-bfab87eea4c8.png" height="511"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989817-3364f1ac-a951-4171-b0c9-1501b3585272.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_22-13-54" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989817-3364f1ac-a951-4171-b0c9-1501b3585272.png" height="57"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989822-82439067-e569-4e12-85b8-79b9cef7e505.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_22-33-32" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989822-82439067-e569-4e12-85b8-79b9cef7e505.png" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989825-8c79c419-cb99-48f8-bab7-8f0bdfc71c74.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-22_22-33-58" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989825-8c79c419-cb99-48f8-bab7-8f0bdfc71c74.png" height="380"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989826-a46a8739-bc13-437b-bb24-5593283ea1b6.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-22_22-36-44" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989826-a46a8739-bc13-437b-bb24-5593283ea1b6.png" height="641"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989832-aad551a6-14be-47ca-89ac-84228ca7818c.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-22_22-37-53" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989832-aad551a6-14be-47ca-89ac-84228ca7818c.png" height="641"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989844-4291705a-c8f0-4797-8951-8f3ac24b54ef.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_22-41-20" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989844-4291705a-c8f0-4797-8951-8f3ac24b54ef.png" height="641"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989846-3ff75a43-3d41-4202-b653-9126f260e564.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-22_23-12-28" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989846-3ff75a43-3d41-4202-b653-9126f260e564.png" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's edit system configuration needed for SAP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Update Hostname
sudo vim /etc/hostname

Check the IP Address
sudo ip addr show
sudo vim /etc/hosts
sudo cat /etc/hosts


Check Hosts and Hostname
sudo cat /etc/hosts
sudo cat /etc/hostname

Restart System after changes and validate the changes
sudo reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989856-a50edff2-9548-49a6-961d-26d9db376ab4.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_23-25-10" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989856-a50edff2-9548-49a6-961d-26d9db376ab4.png" height="274"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989859-4eb2e3ce-fa1c-4871-90df-001c8d3857aa.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_23-26-11" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989859-4eb2e3ce-fa1c-4871-90df-001c8d3857aa.png" height="629"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989862-7a5c4d97-5913-43c5-8a34-7c55e9d1bb24.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_23-26-32" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989862-7a5c4d97-5913-43c5-8a34-7c55e9d1bb24.png" height="378"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989865-c2807310-07b4-4f09-9546-d464450b9780.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_23-31-02" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989865-c2807310-07b4-4f09-9546-d464450b9780.png" height="143"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989868-3baddaac-117c-4516-aa1a-3088030e5026.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_23-36-22" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989868-3baddaac-117c-4516-aa1a-3088030e5026.png" height="768"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989870-8c455c5e-1602-4338-9386-6d424e19cede.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-22_23-39-54" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989870-8c455c5e-1602-4338-9386-6d424e19cede.png" height="430"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989873-bec0a957-4196-459c-b7f3-19e34aa0d5aa.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_23-47-08" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989873-bec0a957-4196-459c-b7f3-19e34aa0d5aa.png" height="153"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989875-be08c515-1fc8-4d19-b2d3-b479c2f90bfe.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-22_23-56-19" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989875-be08c515-1fc8-4d19-b2d3-b479c2f90bfe.png" height="397"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989878-6d6408e7-496f-4719-a353-78b5ee7f016b.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_01-25-24" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F226989878-6d6408e7-496f-4719-a353-78b5ee7f016b.png" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the installation of netWeaver is completed, let's install SAP frontend GUI to access the netweaver.&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%2Fuser-images.githubusercontent.com%2F116753469%2F227099695-dee58325-2a04-4811-ba94-0e3dc5cb5720.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_10-43-29" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227099695-dee58325-2a04-4811-ba94-0e3dc5cb5720.png" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add a new connection&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227099829-d3c68c8d-583a-4d34-98ee-0407d62647a9.png" class="article-body-image-wrapper"&gt;&lt;img width="726" alt="Snipaste_2023-03-23_10-44-40" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227099829-d3c68c8d-583a-4d34-98ee-0407d62647a9.png" height="741"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give the connection a name, and add the public ip address assigned to the SAP and save 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%2Fuser-images.githubusercontent.com%2F116753469%2F227099874-dda82ae1-e7df-42a5-bd81-f9c341963e74.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_10-47-53" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227099874-dda82ae1-e7df-42a5-bd81-f9c341963e74.png" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now add the credentials, generally if it is developer ABAP SPO2 7.52 version, the default details are&lt;br&gt;
Client: 001&lt;br&gt;
username: SAP*&lt;br&gt;
password: Appl1ance&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%2Fuser-images.githubusercontent.com%2F116753469%2F227101634-5b325494-e593-47e0-8cb9-bf52f39d2b20.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_10-48-42" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101634-5b325494-e593-47e0-8cb9-bf52f39d2b20.png" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's add a user, type SU01 in the searchbox, Select create user&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101764-b5e39e29-d2cc-4333-9bbd-c51b2f4e4a82.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_11-05-28" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101764-b5e39e29-d2cc-4333-9bbd-c51b2f4e4a82.png" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101850-58936c4d-f1aa-4eae-8aba-615879414ef9.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-09-12" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101850-58936c4d-f1aa-4eae-8aba-615879414ef9.png" height="863"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101939-2eec86df-a603-4b57-85bf-ea8119bce67b.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-12-34" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101939-2eec86df-a603-4b57-85bf-ea8119bce67b.png" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101950-a71af954-0520-4105-94d0-dbcfbded7b9b.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-15-23" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101950-a71af954-0520-4105-94d0-dbcfbded7b9b.png" height="424"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101983-5aeab76f-472e-4b99-9a91-61f2eab3ffc1.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_11-16-48" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227101983-5aeab76f-472e-4b99-9a91-61f2eab3ffc1.png" height="422"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102018-1c12def2-00c0-46d4-8137-0c6858e08a6f.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-17-56" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102018-1c12def2-00c0-46d4-8137-0c6858e08a6f.png" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the user is created.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102050-7f5c17e7-af27-40c1-a87e-e123b657ec8f.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-18-20" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102050-7f5c17e7-af27-40c1-a87e-e123b657ec8f.png" height="424"&gt;&lt;/a&gt;&lt;br&gt;
we'll use this created user to login to SAP now&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102173-5fdde8b7-ba3a-40af-bfc7-7d2bd364cda6.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-19-39" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102173-5fdde8b7-ba3a-40af-bfc7-7d2bd364cda6.png" height="491"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102239-9614e649-12ca-438a-bf98-c1d099def97a.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-20-01" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102239-9614e649-12ca-438a-bf98-c1d099def97a.png" height="404"&gt;&lt;/a&gt;&lt;br&gt;
Now we're logged in as created user.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102335-c8ffd253-fe13-4238-9f42-afeac41c34f9.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_11-20-31" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102335-c8ffd253-fe13-4238-9f42-afeac41c34f9.png" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Convert the EC2 instance into an OVA file and store it in Amazon S3
&lt;/h3&gt;

&lt;p&gt;Use the AWS CLI to convert the EC2 instance into an OVA file and store it in Amazon S3. Ensure that the OVA file is stored in a secure and accessible location. &lt;/p&gt;

&lt;p&gt;for this step if we want to convert manually to let's say to VMware platform we can use below cli to convert format and export it.&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/vm-import/latest/userguide/vmexport.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/vm-import/latest/userguide/vmexport.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But in my case to make it easier, I am just creating image from the current VM in next step utilizing AWS automation to reduce manual overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Create an Amazon Machine Image (AMI) and EBS snapshot
&lt;/h3&gt;

&lt;p&gt;Ensure that the AMI and EBS snapshot are properly configured and tagged for easy identification.&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%2Fuser-images.githubusercontent.com%2F116753469%2F227102780-b4fd2b8d-8752-4858-8bfb-94f9e010446e.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_11-49-32" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227102780-b4fd2b8d-8752-4858-8bfb-94f9e010446e.png" height="300"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103152-a47a3848-5be3-4207-b6de-6b8cf698025f.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-03-50" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103152-a47a3848-5be3-4207-b6de-6b8cf698025f.png" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait until the AMI becomes available, it will take a while.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103057-09a571d7-2e02-4cf9-9a34-b9e660e8bb32.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_11-50-57" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103057-09a571d7-2e02-4cf9-9a34-b9e660e8bb32.png" height="95"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103166-dc9b6509-bdd6-4d03-92b6-3ec18cd224d2.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-39-10" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103166-dc9b6509-bdd6-4d03-92b6-3ec18cd224d2.png" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Launch a new EC2 instance from the AMI and EBS snapshot in the new AWS environment
&lt;/h3&gt;

&lt;p&gt;Now, let's Launch a new EC2 instance from the AMI and EBS snapshot in the new AWS environment with same config as previous instance. &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%2Fuser-images.githubusercontent.com%2F116753469%2F227103374-ed5c29ba-26d5-40f6-9c0b-3463fea70976.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-40-12" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103374-ed5c29ba-26d5-40f6-9c0b-3463fea70976.png" height="519"&gt;&lt;/a&gt;&lt;br&gt;
wait until it comes to active status&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103457-d0d02de3-5723-4f86-8df7-273a4a2e17c9.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-40-43" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103457-d0d02de3-5723-4f86-8df7-273a4a2e17c9.png" height="124"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103471-de5d175d-e355-44a1-8b59-fd98f8f8bcc8.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-40-57" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103471-de5d175d-e355-44a1-8b59-fd98f8f8bcc8.png" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now note down the new public ip of the migrated instance&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103569-4dd8ba29-47c0-4180-bbe2-e73ae3d1af0c.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-42-07" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103569-4dd8ba29-47c0-4180-bbe2-e73ae3d1af0c.png" height="425"&gt;&lt;/a&gt;&lt;br&gt;
Now let's create a new connection to the new instance with the noted ip address.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103729-78ba223f-912a-4f66-aeeb-47c4a4f03905.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-44-43" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103729-78ba223f-912a-4f66-aeeb-47c4a4f03905.png" height="739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now instead of default login credentials, let's use the user and it's credentials we created to check if the migrated VM is same as the previous VM.&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%2Fuser-images.githubusercontent.com%2F116753469%2F227103875-ad941a1e-9eb1-4d3b-afdd-f0a77ddc2205.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_12-53-00" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103875-ad941a1e-9eb1-4d3b-afdd-f0a77ddc2205.png" height="471"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103905-69b5cf05-a9b3-4220-936d-c101cecd423e.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_12-54-05" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227103905-69b5cf05-a9b3-4220-936d-c101cecd423e.png" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we Ensured that the instance is properly configured and that SAP NetWeaver is running correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Cleanup
&lt;/h3&gt;

&lt;p&gt;Now to reduce any further costs, delete the EC2 instances launched, deregister AMI and delete the snapshot.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>migration</category>
      <category>sap</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Database Migration from OnPrem to AWS RDS</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Sat, 31 Aug 2024 16:10:25 +0000</pubDate>
      <link>https://dev.to/prakash_rao/database-migration-from-onprem-to-aws-rds-5h01</link>
      <guid>https://dev.to/prakash_rao/database-migration-from-onprem-to-aws-rds-5h01</guid>
      <description>&lt;p&gt;This project provides a step-by-step guide on how to migrate a WordPress website and MariaDB database from on-premises to AWS, using peering connections and AWS services such as EC2, RDS, and DMS. The guide covers setting up the simulated environment, creating VPC and peering connection, launching instances, setting up DMS replication, and testing..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcftzmux5cfwp7pjvwqe1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcftzmux5cfwp7pjvwqe1.png" alt="dms" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;To use this project, you need to have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A simulated AWS on-prem env with a WordPress website and MariaDB database.&lt;/li&gt;
&lt;li&gt;An AWS account with access to EC2, RDS, and DMS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The guide covers the following steps:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Assuming a simulated on-premises environment on AWS with a WordPress website and MariaDB database are already setup.&lt;/li&gt;
&lt;li&gt;Create an AWS VPC and peering connection between the on-premises (simulated) environment and the AWS VPC.&lt;/li&gt;
&lt;li&gt;Launch an EC2 instance in the AWS VPC and configure it as the new webserver for the WordPress website.&lt;/li&gt;
&lt;li&gt;Launch an RDS instance in the AWS VPC and configure it as the new database server for the MariaDB database.&lt;/li&gt;
&lt;li&gt;Set up DMS replication instance between the on-premises MariaDB database and the AWS RDS instance and start replicating.&lt;/li&gt;
&lt;li&gt;Test the migrated WordPress website by modifying the wordpress file where the ip is pointed to on-prem to DNS of MariaDB database.&lt;/li&gt;
&lt;li&gt;As a cleanup delete the instances, peering connection, DMS replication instance, RDS, EC2, etc.&lt;/li&gt;
&lt;/ol&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%2Fuser-images.githubusercontent.com%2F116753469%2F227181289-57823415-18d4-4f00-8d8e-324ad7fa6797.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-05-08" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181289-57823415-18d4-4f00-8d8e-324ad7fa6797.png" height="199"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181299-4e34fd22-5c16-4f84-8128-b19071db21a2.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-06-28" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181299-4e34fd22-5c16-4f84-8128-b19071db21a2.png" height="255"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181300-69cc6bf6-5a0e-4b37-bd34-4c5950b121fd.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-07-51" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181300-69cc6bf6-5a0e-4b37-bd34-4c5950b121fd.png" height="1103"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181307-df1bebf3-3391-4bc9-8a7d-753775a41007.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-08-34" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181307-df1bebf3-3391-4bc9-8a7d-753775a41007.png" height="435"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181312-ca73feb3-4941-4e38-aa01-a6d0bcd47f04.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-08-59" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181312-ca73feb3-4941-4e38-aa01-a6d0bcd47f04.png" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181318-b37508d3-5891-4e15-9434-2e9593820ea7.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-16-40" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181318-b37508d3-5891-4e15-9434-2e9593820ea7.png" height="434"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181322-e84728d6-a8d8-4915-881e-8e27c18aaeb1.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_17-17-56" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181322-e84728d6-a8d8-4915-881e-8e27c18aaeb1.png" height="274"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181325-25f3a721-3337-46be-992d-ae07212fd0ad.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-19-07" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181325-25f3a721-3337-46be-992d-ae07212fd0ad.png" height="440"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181332-14a98300-f45d-4d5b-9efd-fe16a13dac09.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_17-19-44" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181332-14a98300-f45d-4d5b-9efd-fe16a13dac09.png" height="445"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181336-01f02e9d-9b39-4a40-aabd-cd6b5261b129.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-20-41" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181336-01f02e9d-9b39-4a40-aabd-cd6b5261b129.png" height="269"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181337-b2282e3c-739b-4916-9294-52b208c3eb2f.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-21-12" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181337-b2282e3c-739b-4916-9294-52b208c3eb2f.png" height="432"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181343-7dd7eed4-24aa-46d3-9704-cf5a1a79caae.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-21-39" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181343-7dd7eed4-24aa-46d3-9704-cf5a1a79caae.png" height="233"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181345-aa3e0112-01e5-4b66-a877-a86dea2f3f4a.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-23-41" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181345-aa3e0112-01e5-4b66-a877-a86dea2f3f4a.png" height="411"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181346-39be9004-ce9c-447e-b1a3-c09c093ea43c.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-26-10" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181346-39be9004-ce9c-447e-b1a3-c09c093ea43c.png" height="476"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181349-9f24e11e-1215-414a-9021-984958b052d9.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_17-35-09" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181349-9f24e11e-1215-414a-9021-984958b052d9.png" height="357"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181350-17fa72a1-7388-49ad-a6ac-7046d899cbb5.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-38-33" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181350-17fa72a1-7388-49ad-a6ac-7046d899cbb5.png" height="1084"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181352-391fc823-d393-4f62-bde7-5d733f67be97.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_17-38-59" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181352-391fc823-d393-4f62-bde7-5d733f67be97.png" height="237"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181358-2bdca51d-4bc7-445e-830d-57d69ae7f17a.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-40-16" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181358-2bdca51d-4bc7-445e-830d-57d69ae7f17a.png" height="512"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181360-fecc131d-1be6-4de3-9afc-5be69d53615a.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-42-15" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181360-fecc131d-1be6-4de3-9afc-5be69d53615a.png" height="425"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181363-96a728c0-16d2-43bc-b2a0-c6128e6fd149.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-43-14" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181363-96a728c0-16d2-43bc-b2a0-c6128e6fd149.png" height="685"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181364-c8852245-a24d-43fa-b160-88c86066591c.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-44-38" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181364-c8852245-a24d-43fa-b160-88c86066591c.png" height="495"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181367-a726d4c0-a3a2-430d-aac6-9059cf62a761.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-46-20" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181367-a726d4c0-a3a2-430d-aac6-9059cf62a761.png" height="822"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181373-f300acf3-0f85-4c56-82fa-93ae1fd5c033.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_17-47-26" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181373-f300acf3-0f85-4c56-82fa-93ae1fd5c033.png" height="389"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181376-b44e20dc-247e-4524-a978-9440f9a3189c.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-47-43" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181376-b44e20dc-247e-4524-a978-9440f9a3189c.png" height="478"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181377-284bbec8-2d24-4218-a9c3-8c915d865de4.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-48-42" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181377-284bbec8-2d24-4218-a9c3-8c915d865de4.png" height="693"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181380-292a286f-b2bd-4f81-910e-9c86be36f688.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-49-56" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181380-292a286f-b2bd-4f81-910e-9c86be36f688.png" height="286"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181383-17661b4a-db52-4115-8547-58dac37950b7.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-50-23" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181383-17661b4a-db52-4115-8547-58dac37950b7.png" height="557"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181385-d946c6be-95ef-45f9-8921-193ebf4778c2.png" class="article-body-image-wrapper"&gt;&lt;img width="796" alt="Snipaste_2023-03-23_17-51-54" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181385-d946c6be-95ef-45f9-8921-193ebf4778c2.png" height="89"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181388-36147e78-350f-4cbf-806a-93075012a1f8.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-54-05" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181388-36147e78-350f-4cbf-806a-93075012a1f8.png" height="777"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181392-beb4a5bf-50dd-4487-a974-ddd01ce83aef.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-54-41" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181392-beb4a5bf-50dd-4487-a974-ddd01ce83aef.png" height="806"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181395-716964e1-2d68-4b68-8593-23c3725a7a2e.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_17-55-57" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181395-716964e1-2d68-4b68-8593-23c3725a7a2e.png" height="371"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181398-7144ee84-f64f-4cfc-a6e4-98a2334dd24c.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-56-16" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181398-7144ee84-f64f-4cfc-a6e4-98a2334dd24c.png" height="322"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181401-a70ba4bb-beca-46fd-b67c-37236b15519b.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-58-03" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181401-a70ba4bb-beca-46fd-b67c-37236b15519b.png" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181404-8d92a1d2-146e-431e-a7da-3aa463851453.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-58-17" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181404-8d92a1d2-146e-431e-a7da-3aa463851453.png" height="438"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181406-86b6b37e-a850-4c72-b22d-f4d01b95e175.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_17-58-32" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181406-86b6b37e-a850-4c72-b22d-f4d01b95e175.png" height="603"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181409-aa41d1c9-aa82-4fd7-b4d6-420af1162d93.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_17-59-05" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181409-aa41d1c9-aa82-4fd7-b4d6-420af1162d93.png" height="107"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181412-82184347-ab8d-48c0-b140-e3f6cd9d450d.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-01-21" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181412-82184347-ab8d-48c0-b140-e3f6cd9d450d.png" height="107"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181416-b8a8df02-9478-4b4d-b522-1df79d73f514.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-01-59" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181416-b8a8df02-9478-4b4d-b522-1df79d73f514.png" height="285"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181419-7cf76706-84dd-4576-bab0-442f9f5c4d5e.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-02-57" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181419-7cf76706-84dd-4576-bab0-442f9f5c4d5e.png" height="411"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181422-f6a82897-e583-430c-9883-667917e0726e.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-03-52" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181422-f6a82897-e583-430c-9883-667917e0726e.png" height="352"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181424-485190ed-9697-46de-bca9-55ece33e3a17.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-04-42" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181424-485190ed-9697-46de-bca9-55ece33e3a17.png" height="213"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181430-9dae4bce-aa25-449c-82f1-fe0e22c2ed71.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-06-48" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181430-9dae4bce-aa25-449c-82f1-fe0e22c2ed71.png" height="221"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181433-1e185f4e-a19e-4cf9-81d6-c4a13cdd651a.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-08-08" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181433-1e185f4e-a19e-4cf9-81d6-c4a13cdd651a.png" height="307"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181439-f7784479-295f-446c-a8cb-b5fe1bbc4680.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-10-56" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181439-f7784479-295f-446c-a8cb-b5fe1bbc4680.png" height="223"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181443-5a911a6c-9ea5-42a6-8829-2bfe34a8635b.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-16-02" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181443-5a911a6c-9ea5-42a6-8829-2bfe34a8635b.png" height="185"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181445-283a12f7-fa2c-458a-b521-03f63d5ff064.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-17-12" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181445-283a12f7-fa2c-458a-b521-03f63d5ff064.png" height="126"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181449-678c0c3c-4b1e-4f5c-ae0e-9e661f091660.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-19-50" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181449-678c0c3c-4b1e-4f5c-ae0e-9e661f091660.png" height="257"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181452-4da21ca5-641c-4f8e-8c34-f8ad32e966cf.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-23-02" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181452-4da21ca5-641c-4f8e-8c34-f8ad32e966cf.png" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181453-d0628993-05ab-4653-9f45-24b2ac956401.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-24-06" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181453-d0628993-05ab-4653-9f45-24b2ac956401.png" height="142"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181456-fe82f27e-afd7-4dfd-8725-c789a995c766.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-24-40" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181456-fe82f27e-afd7-4dfd-8725-c789a995c766.png" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181462-2fde629a-81dc-40db-876d-48c5c25725c4.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-31-20" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181462-2fde629a-81dc-40db-876d-48c5c25725c4.png" height="439"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181465-8b41c292-5cf4-49f1-97f9-5fa0c528c771.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-32-03" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181465-8b41c292-5cf4-49f1-97f9-5fa0c528c771.png" height="327"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181466-db0f0a54-11a3-4379-81a6-7146220b23d9.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-33-27" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181466-db0f0a54-11a3-4379-81a6-7146220b23d9.png" height="658"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181471-4a9a2371-f484-48a8-9d2b-d3d202f0012e.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-34-00" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181471-4a9a2371-f484-48a8-9d2b-d3d202f0012e.png" height="244"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181477-704298ae-c6d6-4ed7-9ce2-22e2392aff40.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-36-15" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181477-704298ae-c6d6-4ed7-9ce2-22e2392aff40.png" height="668"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181479-8254b252-b55b-4f81-9e9c-09404d43e286.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-36-40" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181479-8254b252-b55b-4f81-9e9c-09404d43e286.png" height="719"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181481-53f5915f-0881-464b-8df2-76faf40b0e3c.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-37-35" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181481-53f5915f-0881-464b-8df2-76faf40b0e3c.png" height="369"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181486-e0d83cb6-f10d-4fe4-987e-0041067eadc6.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-37-52" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181486-e0d83cb6-f10d-4fe4-987e-0041067eadc6.png" height="546"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181488-a533b33b-de2d-4476-b025-b8fc16e7ac4f.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-38-31" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181488-a533b33b-de2d-4476-b025-b8fc16e7ac4f.png" height="299"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181492-6e656fb3-652a-4e75-a3db-1ea27aa8d018.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-42-38" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181492-6e656fb3-652a-4e75-a3db-1ea27aa8d018.png" height="1070"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181495-92a24db3-5a2c-4448-b750-a32b2ddac4a6.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-46-38" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181495-92a24db3-5a2c-4448-b750-a32b2ddac4a6.png" height="597"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181497-68a38c6b-bfce-48c0-8aa0-d1baa1f035c6.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_18-47-13" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181497-68a38c6b-bfce-48c0-8aa0-d1baa1f035c6.png" height="537"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181502-365f6a42-6b5e-4113-8ff3-ee82b21eff80.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-55-21" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181502-365f6a42-6b5e-4113-8ff3-ee82b21eff80.png" height="167"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181506-27ae3890-572c-4630-a27d-735f1591ba29.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_18-55-50" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181506-27ae3890-572c-4630-a27d-735f1591ba29.png" height="309"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181508-10d692cf-8bcb-4139-9d65-82e1abe50542.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_19-00-37" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181508-10d692cf-8bcb-4139-9d65-82e1abe50542.png" height="648"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181513-616f544f-d5df-4e4d-be1e-9c985c87e8fe.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_19-01-04" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181513-616f544f-d5df-4e4d-be1e-9c985c87e8fe.png" height="667"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181518-67feadd4-f431-4bd2-a475-724790f392e3.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_19-01-57" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181518-67feadd4-f431-4bd2-a475-724790f392e3.png" height="171"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181521-544fbe1d-baf4-457b-96a1-2784c45a5eba.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_19-02-44" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181521-544fbe1d-baf4-457b-96a1-2784c45a5eba.png" height="119"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181523-1d78e255-779a-4094-adb2-5e94176bc21b.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_19-06-03" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181523-1d78e255-779a-4094-adb2-5e94176bc21b.png" height="122"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181525-6edd73e1-5abd-4f3d-a085-6f7c815832e7.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_19-07-38" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181525-6edd73e1-5abd-4f3d-a085-6f7c815832e7.png" height="159"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181531-a0a9a9d7-9718-449b-afc5-7c10955a8aa9.png" class="article-body-image-wrapper"&gt;&lt;img width="799" alt="Snipaste_2023-03-23_19-09-54" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181531-a0a9a9d7-9718-449b-afc5-7c10955a8aa9.png" height="146"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181532-130d9888-31eb-4ae4-bc4b-d25892fc100a.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_19-12-56" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181532-130d9888-31eb-4ae4-bc4b-d25892fc100a.png" height="109"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181535-ca4c3368-e614-4149-b59e-de3b41b26058.png" class="article-body-image-wrapper"&gt;&lt;img width="800" alt="Snipaste_2023-03-23_19-13-09" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F116753469%2F227181535-ca4c3368-e614-4149-b59e-de3b41b26058.png" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CleanUp:
&lt;/h2&gt;

&lt;p&gt;At the end as a cleanup delete the instances, peering connection, DMS replication instance, RDS, EC2, etc.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>dbmigration</category>
      <category>rds</category>
    </item>
    <item>
      <title>Deploying a "Hello World" Application to AWS Elastic Beanstalk</title>
      <dc:creator>Prakash Rao</dc:creator>
      <pubDate>Mon, 17 Jun 2024 23:36:11 +0000</pubDate>
      <link>https://dev.to/prakash_rao/deploying-a-hello-world-application-to-aws-elastic-beanstalk-pag</link>
      <guid>https://dev.to/prakash_rao/deploying-a-hello-world-application-to-aws-elastic-beanstalk-pag</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
AWS Elastic Beanstalk as an easy-to-use service for deploying and scaling web applications and services developed with Java, .NET, PHP, Node.js, Python, Ruby, Go, and Docker on familiar servers such as Apache, Nginx, Passenger, and IIS. This post will demonstrate how to deploy your application in AWS Elastic Beanstalk.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS account&lt;/li&gt;
&lt;li&gt;Basic knowledge of web application development&lt;/li&gt;
&lt;li&gt;Familiarity with AWS services is helpful but not required&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Creating a Simple Web Application
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Initial Setup&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose a programming language and framework. For this example, let's use Python with Flask.&lt;/li&gt;
&lt;li&gt;Create a new directory for your project and navigate into it.&lt;/li&gt;
&lt;li&gt;Initialize a new Python virtual environment and activate it (optional but recommended).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Application Code&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a file named application.py and add the following Flask application code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask import Flask

application = Flask(__name__)

@application.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    application.run()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a requirements.txt file specifying Flask:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask==1.1.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Local Testing (Optional)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the application locally to ensure it works.&lt;/li&gt;
&lt;li&gt;Open a browser and navigate to &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt; to see the "Hello, World!" message.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Preparing the Application for Deployment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Zip the application.py and requirements.txt files together.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;zip myapp.zip application.py requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Creating an Elastic Beanstalk Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Log in to the AWS Management Console.&lt;/li&gt;
&lt;li&gt;Navigate to the Elastic Beanstalk service and click "Create New Application".&lt;/li&gt;
&lt;li&gt;Enter an application name and description.&lt;/li&gt;
&lt;li&gt;Create a new environment within this application – choose the Web server environment.&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.amazonaws.com%2Fuploads%2Farticles%2Fsswwzw8ymrlieueqcjej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsswwzw8ymrlieueqcjej.png" alt=" " width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the Python platform and choose the appropriate version.&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.amazonaws.com%2Fuploads%2Farticles%2Fm4usb5iyxordc40sddlh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4usb5iyxordc40sddlh.png" alt=" " width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Uploading and Deploying the Application
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When prompted to upload your code, choose the "Upload your code" option and upload the myapp.zip file.&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.amazonaws.com%2Fuploads%2Farticles%2Fae188lmaioi86s0hvhjx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fae188lmaioi86s0hvhjx.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure more options if needed, or simply click "Create environment".&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.amazonaws.com%2Fuploads%2Farticles%2Fnfk6yva6fg80ty2szysf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfk6yva6fg80ty2szysf.png" alt=" " width="799" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Configuring Service Access
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For Elastic Beanstalk selecting role is crucial. For this lab purpose let's chose existing service role and existing EC2 instance profile.&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.amazonaws.com%2Fuploads%2Farticles%2Fhrkgmjw8e9fm4utzcst7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrkgmjw8e9fm4utzcst7.png" alt=" " width="799" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Environment Configuration and Launch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For rest of the optional parameters, keep it as is.&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.amazonaws.com%2Fuploads%2Farticles%2Frmqb5pl8299hzj30ua4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmqb5pl8299hzj30ua4v.png" alt=" " width="291" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Elastic Beanstalk will now create your environment and deploy the application.&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.amazonaws.com%2Fuploads%2Farticles%2Ftyr44iqhh4ndvcmyve1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftyr44iqhh4ndvcmyve1h.png" alt=" " width="800" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This process might take a few minutes.&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.amazonaws.com%2Fuploads%2Farticles%2Fnfmd3hplnq4cskn4pw90.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfmd3hplnq4cskn4pw90.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Accessing the Deployed Application
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Once the environment is ready, click the provided URL to access your application.&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.amazonaws.com%2Fuploads%2Farticles%2Fdygnp5emofpvt7f9r9kf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdygnp5emofpvt7f9r9kf.png" alt=" " width="799" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You should see the "Hello, World!" message served from AWS Elastic Beanstalk.&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.amazonaws.com%2Fuploads%2Farticles%2Fkikfpcoiellmpd7sz7zf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkikfpcoiellmpd7sz7zf.png" alt=" " width="797" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Clean Up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To avoid incurring charges, delete the Elastic Beanstalk environment and application.&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.amazonaws.com%2Fuploads%2Farticles%2Fubidvclbcubxwtaa4tkk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubidvclbcubxwtaa4tkk.png" alt=" " width="798" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Congratulations! You've just taken a significant step into the world of web application deployment using AWS Elastic Beanstalk. By following the steps outlined in this post, you have learned how to deploy a "Hello World" application.&lt;/p&gt;

&lt;p&gt;As you become more comfortable with AWS Elastic Beanstalk, I encourage you to explore its advanced features, experiment with different configurations, and consider how you can integrate other AWS services to enhance your application's functionality and performance.&lt;/p&gt;

&lt;p&gt;Now that you have the basics down, the sky is the limit. Keep learning, keep experimenting, and most importantly, have fun building!&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;p&gt;To further your knowledge and skills in AWS Elastic Beanstalk and related AWS services, here are some additional resources you may find useful:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/" rel="noopener noreferrer"&gt;AWS Elastic Beanstalk Developer Guide&lt;/a&gt;: The official Elastic Beanstalk documentation provides detailed information on how to use and configure the service.&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/samples.html" rel="noopener noreferrer"&gt;AWS Elastic Beanstalk Sample Applications&lt;/a&gt;: Explore sample applications provided by AWS that you can deploy and study.&lt;br&gt;
&lt;a href="https://www.aws.training/" rel="noopener noreferrer"&gt;AWS Training and Certification&lt;/a&gt;: AWS offers various training courses and certifications that can help you deepen your understanding of AWS services.&lt;br&gt;
&lt;a href="https://forums.aws.amazon.com/forum.jspa?forumID=86" rel="noopener noreferrer"&gt;AWS Developer Forums&lt;/a&gt;: Elastic Beanstalk: Join the community forum to ask questions, share experiences, and get insights from other AWS developers.&lt;br&gt;
&lt;a href="https://flask.palletsprojects.com/en/latest/" rel="noopener noreferrer"&gt;Flask Documentation&lt;/a&gt;: The official documentation for Flask is an excellent resource for learning more about building web applications with this micro web framework.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
