<?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: Matias Martinez</title>
    <description>The latest articles on DEV Community by Matias Martinez (@matias_martinez_185d9e0ee).</description>
    <link>https://dev.to/matias_martinez_185d9e0ee</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%2F2610948%2F367b842d-2a5b-47fc-abb1-526da837ee4a.jpg</url>
      <title>DEV Community: Matias Martinez</title>
      <link>https://dev.to/matias_martinez_185d9e0ee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matias_martinez_185d9e0ee"/>
    <language>en</language>
    <item>
      <title>Strands Decider 2B: AWS's open source model that doesn't generate text, it decides</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Tue, 13 Oct 2026 21:25:40 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/strands-decider-2b-awss-open-source-model-that-doesnt-generate-text-it-decides-48gm</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/strands-decider-2b-awss-open-source-model-that-doesnt-generate-text-it-decides-48gm</guid>
      <description>&lt;p&gt;A lot of the LLM calls inside an agent aren't about generating text. They're tiny decisions: which team owns this ticket? Did the user actually say that tool argument, or did the model make it up? Is this message urgent? Cheap model or expensive model? For each one, we ship the full context to a frontier model, wait a second or two, and parse free text that comes with no measure of how confident the model is.&lt;/p&gt;

&lt;p&gt;Strands Labs, the experimental arm of the Strands Agents team at AWS, released &lt;strong&gt;Strands Decider 2B&lt;/strong&gt;, an Apache 2.0 model built for exactly that gap. It doesn't generate text. It takes a state plus a set of questions and, for each one, picks from closed options and returns a calibrated probability. It runs locally, answers in about 115 ms median on a desktop GPU, and plugs into Strands Agents' intervention system to review tool calls before they execute.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;decision model&lt;/strong&gt; (the authors call it a "system one" model): picks options, answers yes/no, or scores on a scale, always with a probability. No text generation.&lt;/li&gt;
&lt;li&gt;Architecture: the &lt;strong&gt;Qwen3.5-2B-Base&lt;/strong&gt; torso with its LM head removed, a ~1M-parameter &lt;strong&gt;pointer head&lt;/strong&gt;, and rank-16 LoRA adapters. One forward pass, no decoding loop.&lt;/li&gt;
&lt;li&gt;First release latency: &lt;strong&gt;115 ms median&lt;/strong&gt; (299 ms p95) on an RTX 3090; 153 ms on an M3 Pro.&lt;/li&gt;
&lt;li&gt;On JevBench (231 public tasks) the current reference model gets 180 right (0.779). Gemma 4 variants reach 207 with the 26B model.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pip install strands-decider&lt;/code&gt;, then use it from the CLI or as a local HTTP server (&lt;code&gt;/v1/systemone&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;It's an experiment, not a managed AWS service. You run it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why now
&lt;/h2&gt;

&lt;p&gt;The "decision model" idea got attention in September when TypeSafe AI came out of stealth with &lt;strong&gt;Jev&lt;/strong&gt;, a proprietary model that returns typed decisions instead of text, available via waitlist at $0.042 per million input tokens. Strands credits Jev for putting the approach on the map and evaluates against JevBench. The difference is distribution: Jev is closed; Strands Decider ships weights, code and the full training recipe.&lt;/p&gt;

&lt;p&gt;There's also a design argument. Ask a chat model "are your own tool arguments grounded?" and it can be talked into yes. A classifier that returns a number your &lt;code&gt;if&lt;/code&gt; statement branches on doesn't negotiate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fowf15x5x0nvifi04thby.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fowf15x5x0nvifi04thby.webp" alt="The model classifies, your code decides" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The decider keeps the transformer torso of Qwen3.5-2B-Base, throws away the vocabulary head, and replaces it with a pointer head. The input has a fixed format: state, question, numbered options, and an &lt;code&gt;&amp;lt;answer&amp;gt;&lt;/code&gt; marker. The head scores each option's final hidden state against the hidden state at &lt;code&gt;&amp;lt;answer&amp;gt;&lt;/code&gt;, a softmax turns those logits into probabilities, done. No tokens generated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm2acxdovtrtc2jdev2wo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm2acxdovtrtc2jdev2wo.webp" alt="Strands Decider 2B architecture. Image: Strands Agents blog (AWS)" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two practical consequences: the head has no per-option parameters, so it can't learn "option 1 is usually right" and you can rename options without retraining; and only the LoRA adapters and the head are trained, which is why the repo can publish the recipe (about 11 hours on one RTX 3090, or ~70 minutes on eight H100s).&lt;/p&gt;

&lt;p&gt;Three question types are supported: &lt;code&gt;noul&lt;/code&gt; (yes/no, returns P(yes)), &lt;code&gt;choice&lt;/code&gt; (one of N), and &lt;code&gt;score&lt;/code&gt; (a level on an ordered rubric). You can ask many questions about one state in a single request; the state is encoded once.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;JevBench (of 231)&lt;/th&gt;
&lt;th&gt;Brier (lower is better)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2B hobson-v19 (launch)&lt;/td&gt;
&lt;td&gt;167&lt;/td&gt;
&lt;td&gt;0.342&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2B hobson-v21&lt;/td&gt;
&lt;td&gt;176&lt;/td&gt;
&lt;td&gt;0.323&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2B qwen3.5-v1-2610 (reference)&lt;/td&gt;
&lt;td&gt;180&lt;/td&gt;
&lt;td&gt;0.280&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E4B gemma4-v1-2610&lt;/td&gt;
&lt;td&gt;187&lt;/td&gt;
&lt;td&gt;0.243&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26B-A4B gemma4-v1-2610&lt;/td&gt;
&lt;td&gt;207&lt;/td&gt;
&lt;td&gt;0.162&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The README itself warns that gaps under ~10 tasks between single runs aren't reliable. For v19, Techstrong.ai reports 100% on easy tasks and 50.5% on hard ones: great at routine, mediocre at complex, which is the pitch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo6yoks8llc15o5rgl4zb.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo6yoks8llc15o5rgl4zb.webp" alt="Accuracy vs. Brier score across training versions. Image: Strands Agents blog (AWS)" width="800" height="654"&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faoyx4tad528pexins6t6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faoyx4tad528pexins6t6.webp" alt="Latency vs. prompt length on an RTX 3090. Image: Strands Agents blog (AWS)" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-on
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;strands-decider

strands-decider ask StrandsAgents/strands-decider-2B-qwen3.5-v1-2610 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--state&lt;/span&gt; &lt;span class="s2"&gt;"Help! My payouts have been failing for 3 days! "&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--choice&lt;/span&gt; &lt;span class="s2"&gt;"Which team should handle this?=billing,sales,retail"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--noul&lt;/span&gt; &lt;span class="s2"&gt;"Does this convey urgency?"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--score&lt;/span&gt; &lt;span class="s2"&gt;"How frustrated is the writer?=calm,frustrated,depressed"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sample output from the README (CPU run): &lt;code&gt;billing&lt;/code&gt; at 0.773, urgency 0.858, and a frustration score of 1.03 with confidence 0.509. That last number is the model telling you it isn't sure, which is information an LLM doesn't give you.&lt;/p&gt;

&lt;p&gt;As a server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;strands-decider serve StrandsAgents/strands-decider-2B-qwen3.5-v1-2610 &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
curl &lt;span class="nt"&gt;-s&lt;/span&gt; localhost:8000/v1/systemone &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"state": "Help! My payouts have been failing for 3 days!",
       "questions": {"is_urgent": {"type": "noul", "instructions": "Does this convey urgency?"}}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server binds to &lt;code&gt;127.0.0.1&lt;/code&gt; and &lt;strong&gt;has no authentication&lt;/strong&gt;. Don't put it behind a public Service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gating tool calls in a Strands agent
&lt;/h3&gt;

&lt;p&gt;This is a trimmed version of &lt;code&gt;examples/strands/&lt;/code&gt; from the repo. The agent has an eager system prompt that makes it guess a city; the decider catches it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;strands&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;strands.interventions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Guide&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InterventionHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Proceed&lt;/span&gt;

&lt;span class="n"&gt;YES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.45&lt;/span&gt;  &lt;span class="c1"&gt;# illustrative threshold; tune it on your own traffic
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ToolCallReviewer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InterventionHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strands-decider-tool-call-reviewer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_decider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decider&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;before_tool_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_use&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# conversation + proposed call
&lt;/span&gt;        &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_decider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QUESTIONS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# args_grounded, premature (noul)
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;args_grounded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Guide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feedback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The arguments look guessed. Ask the user to confirm them.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;premature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;YES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Guide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feedback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Too early to call this tool. Clarify with the user first.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Proceed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Guide&lt;/code&gt; doesn't block the call; it hands the turn back to the model with feedback, and the agent ends up asking "which city?" instead of reporting Seattle's weather. Strands interventions also support &lt;code&gt;Deny&lt;/code&gt; and &lt;code&gt;Confirm&lt;/code&gt; (human approval).&lt;/p&gt;

&lt;h3&gt;
  
  
  Running it on Amazon EKS
&lt;/h3&gt;

&lt;p&gt;Because the server only listens on localhost, the natural Kubernetes pattern is a &lt;strong&gt;sidecar in the agent's pod&lt;/strong&gt;. A native sidecar (an init container with &lt;code&gt;restartPolicy: Always&lt;/code&gt;) starts before the agent and lives as long as the pod. Two gotchas: there's no published container image, so build your own and bake the weights in; and &lt;code&gt;httpGet&lt;/code&gt; probes will always fail because the kubelet hits the pod IP, not 127.0.0.1, so use an &lt;code&gt;exec&lt;/code&gt; probe against &lt;code&gt;http://127.0.0.1:&amp;lt;port&amp;gt;/health&lt;/code&gt;. A g6-family node (NVIDIA L4, 24 GB) is plenty for the 2B model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk4stz6vv7zczb8ojvsdb.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk4stz6vv7zczb8ojvsdb.webp" alt="Decider as a sidecar on Amazon EKS" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;The model is free; you pay for hardware. A g6.xlarge is about $0.805/hour on demand in us-east-1, roughly $588/month always on. Back-of-the-envelope (mine): ~8 sequential decisions/second at ~115 ms is on the order of 20M decisions a month; at 500 tokens each, that volume on a per-token service like Jev would be around $450. Self-hosting wins with sustained volume or privacy requirements; at low volume an idle GPU costs more. Start on CPU, share the GPU, and use the decider as a first-pass filter that escalates low-confidence cases to the LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations worth knowing
&lt;/h2&gt;

&lt;p&gt;Per the model card: rephrased questions often get the same answer, long multi-step documents are the weak spot, &lt;code&gt;score&lt;/code&gt; and &lt;code&gt;noul&lt;/code&gt; transfer poorly to unfamiliar rubrics, and calibration was fitted on short classification, so validate thresholds on your own traffic. Training data and examples are English.&lt;/p&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;The benchmark isn't the point (231 tasks is noisy). The point is the separation: the model classifies and returns a number, your code decides. That turns decisions hidden inside prompts into something you can test, version and audit with explicit thresholds. It's the same logic platform teams apply with Kubernetes admission policies: a deterministic checkpoint before something runs. It's not production-ready, and the official example says its thresholds are illustrative. But I'd run it as a tool-call guardrail for an internal agent, in a pod with a shared GPU, and compare its decisions against what your LLM decides today.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published in Spanish on &lt;a href="https://blog.cloudacademy.ar/strands-decider-2b-modelo-de-decision-open-source-para-agentes/" rel="noopener noreferrer"&gt;CloudAcademy.ar&lt;/a&gt;, with the full Kubernetes manifest and the complete intervention example.&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://strandsagents.com/blog/introducing-strands-decider/" rel="noopener noreferrer"&gt;Introducing Strands Decider 2B&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/strands-labs/strands-decider" rel="noopener noreferrer"&gt;strands-labs/strands-decider on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/strands-labs/strands-decider/tree/main/examples/strands" rel="noopener noreferrer"&gt;Strands agent intervention example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/StrandsAgents/strands-decider-2B-hobson-v19" rel="noopener noreferrer"&gt;Model card on Hugging Face&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techstrong.ai/articles/aws-explores-decision-models-with-strands-decider-2b/" rel="noopener noreferrer"&gt;Techstrong.ai coverage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vktr.com/ai-platforms/chatgpt-cocreator-launches-typesafe-ai-with-jev/" rel="noopener noreferrer"&gt;VKTR: TypeSafe AI launches Jev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>agents</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>AWS Lambda Web Functions: your HTTP server on Lambda, with real concurrency and active-CPU billing</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Tue, 13 Oct 2026 21:18:40 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/aws-lambda-web-functions-your-http-server-on-lambda-with-real-concurrency-and-active-cpu-billing-36eb</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/aws-lambda-web-functions-your-http-server-on-lambda-with-real-concurrency-and-active-cpu-billing-36eb</guid>
      <description>&lt;p&gt;On October 12, AWS launched &lt;strong&gt;Lambda Web Functions&lt;/strong&gt;, and it's the biggest change to Lambda's programming model in years. Instead of writing a handler that receives a JSON event, you ship a plain HTTP server (Express, Hono, Fastify, React Router) that listens on a port. Lambda puts a managed HTTPS endpoint in front of it, scales it with traffic (down to zero), and bills you for the CPU time you actually burn, not for the time your request spent waiting on Postgres.&lt;/p&gt;

&lt;p&gt;Along with the launch, the existing functions were renamed &lt;strong&gt;Lambda Event Functions&lt;/strong&gt; (naming only, no code changes), so Lambda now comes in three shapes: Event Functions, Web Functions, and MicroVMs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffqlywez4a3hvcxq1xkbi.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffqlywez4a3hvcxq1xkbi.webp" alt="The three shapes of AWS Lambda" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Your server listens on the &lt;code&gt;host:port&lt;/code&gt; Lambda passes in &lt;code&gt;AWS_LAMBDA_HTTP_ENDPOINT&lt;/code&gt;. No adapter, no wrapper.&lt;/li&gt;
&lt;li&gt;Each execution environment serves &lt;strong&gt;many requests at once&lt;/strong&gt;: up to 128, default 64.&lt;/li&gt;
&lt;li&gt;Billing is &lt;strong&gt;active CPU + memory consumed while the environment lives + requests&lt;/strong&gt;. In us-east-1 (Arm): $0.0000276944 per vCPU-second, $0.0000036667 per GB-second, $0.30 per million requests.&lt;/li&gt;
&lt;li&gt;One-command deploy: &lt;code&gt;aws lambda-web deploy --name my-app --code ./my-app&lt;/code&gt;. Add &lt;code&gt;--regions&lt;/code&gt; for a global endpoint with latency-based routing.&lt;/li&gt;
&lt;li&gt;Immutable revisions plus weighted endpoints give you canary, blue/green and rollback out of the box.&lt;/li&gt;
&lt;li&gt;Node.js 24 on Arm64 only, 2 GB per environment, 3–900 s request timeout.&lt;/li&gt;
&lt;li&gt;Available in us-east-1, us-east-2, us-west-2, ap-northeast-1 and eu-west-1. Not in São Paulo yet.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Running web apps on Lambda was always possible, but awkward. You wrapped your framework with &lt;code&gt;serverless-http&lt;/code&gt; or the Lambda Web Adapter, and each environment still handled exactly one request. If your API took 200 ms because it was waiting on a database, you paid for 200 ms of compute while the CPU idled most of that time. A burst of 50 concurrent requests meant up to 50 environments and 50 cold starts.&lt;/p&gt;

&lt;p&gt;That model fits short, event-driven functions. It fits LLM-backed APIs terribly: a request that streams tokens for three seconds while the CPU mostly waits is the worst case for wall-clock billing and single-request isolation. Web Functions is AWS's answer, and it's no coincidence the launch post lists streaming inference endpoints among the first use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The resource model: functions, revisions, endpoints
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Web Function&lt;/strong&gt;: the top-level resource.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revision&lt;/strong&gt;: an immutable snapshot of code and configuration (timeout, per-environment concurrency, env vars, execution role). Any change means a new revision, and a new revision doesn't inherit settings from the previous one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint&lt;/strong&gt;: the HTTPS entry point, with its own domain, auth type and scaling limits. It routes to one or two revisions by weight.&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwg3awrncd0djprmr9m7.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwg3awrncd0djprmr9m7.webp" alt="Web Function resource model: prod endpoint split 90/10, staging endpoint at 100% on revision 2. Image: AWS documentation" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Endpoints come in three types, fixed at creation: &lt;code&gt;HomeRegion&lt;/code&gt; (one Region, one domain), &lt;code&gt;MultiRegion&lt;/code&gt; (several Regions behind a global &lt;code&gt;*.lambda-web.global.on.aws&lt;/code&gt; domain with best-effort latency routing), and &lt;code&gt;PerRegion&lt;/code&gt; (one domain per Region, you route).&lt;/p&gt;

&lt;p&gt;Each environment goes through init, ready and shutdown. Your server must start listening &lt;strong&gt;within 10 seconds&lt;/strong&gt;; listening on the port is the readiness signal, there's no separate health check. On shutdown you get &lt;code&gt;SIGTERM&lt;/code&gt; and &lt;strong&gt;one second&lt;/strong&gt; to clean up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feqkvpaivqgs8espa99x3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feqkvpaivqgs8espa99x3.webp" alt="Execution environment lifecycle. Image: AWS documentation" width="799" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrency and scaling
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxConcurrencyPerEnvironment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Revision&lt;/td&gt;
&lt;td&gt;1–128&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxEnvironments&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Endpoint, per Region&lt;/td&gt;
&lt;td&gt;2–10,000 (optional)&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rateLimit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Endpoint, per Region&lt;/td&gt;
&lt;td&gt;0–10,000 RPS (optional)&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeoutSeconds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Revision&lt;/td&gt;
&lt;td&gt;3–900&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Account quotas apply per Region even if you set nothing: 10,000 RPS per endpoint, 100,000 RPS per account, and 2,000 vCPUs. Each environment uses 2 vCPUs, so that's at most 1,000 environments per Region. Lambda keeps headroom to absorb gradual increases; bursts larger than the headroom wait on cold starts. When you hit a limit you get a 429 (not queued); a &lt;code&gt;rateLimit&lt;/code&gt; of 0 returns &lt;code&gt;503 Platform.EndpointDisabled&lt;/code&gt;, which doubles as a kill switch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flgzr1tqpzp35tlsn2x2n.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flgzr1tqpzp35tlsn2x2n.webp" alt="Scaling headroom vs. traffic burst. Image: AWS documentation" width="799" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-on
&lt;/h2&gt;

&lt;p&gt;The only code change versus running locally is where you listen:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from Lambda Web Functions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_LAMBDA_HTTP_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// you get ~1s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy (make sure your AWS CLI v2 has &lt;code&gt;aws lambda-web&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda-web deploy &lt;span class="nt"&gt;--name&lt;/span&gt; my-api &lt;span class="nt"&gt;--code&lt;/span&gt; ./my-api &lt;span class="nt"&gt;--auth-type&lt;/span&gt; IamAuth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;strong&gt;&lt;code&gt;deploy&lt;/code&gt; creates an &lt;code&gt;ApplicationManaged&lt;/code&gt; (public, no auth) endpoint by default&lt;/strong&gt;. Great for hello world, not for production accounts. The docs include an SCP that denies creating such endpoints via the &lt;code&gt;lambda:Request/WebFunctionAuthType&lt;/code&gt; condition key.&lt;/p&gt;

&lt;p&gt;Canary and rollback are just weight updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda-web update-web-function-endpoint &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; my-api &lt;span class="nt"&gt;--endpoint-name&lt;/span&gt; prod &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--revision-weights&lt;/span&gt; &lt;span class="s1"&gt;'[{"revisionId": "rev-abc12", "weight": 90}, {"revisionId": "rev-def45", "weight": 10}]'&lt;/span&gt;

&lt;span class="c"&gt;# rollback (include the mode so it works from any state)&lt;/span&gt;
aws lambda-web update-web-function-endpoint &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; my-api &lt;span class="nt"&gt;--endpoint-name&lt;/span&gt; prod &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--auto-deployment-mode&lt;/span&gt; Disabled &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--revision-weights&lt;/span&gt; &lt;span class="s1"&gt;'[{"revisionId": "rev-abc12", "weight": 100}]'&lt;/span&gt;
&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm7nx9u3mwtyymz963f9v.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm7nx9u3mwtyymz963f9v.webp" alt="Canary deployment with revision weights. Image: AWS documentation" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Protect your downstream database without a new revision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda-web update-web-function-endpoint &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; my-api &lt;span class="nt"&gt;--endpoint-name&lt;/span&gt; prod &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--scaling-config&lt;/span&gt; &lt;span class="s1"&gt;'{"maxEnvironments": 50}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--throttle-config&lt;/span&gt; &lt;span class="s1"&gt;'{"rateLimit": 8000}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a custom domain and AWS WAF, put CloudFront in front with &lt;strong&gt;Origin Access Control&lt;/strong&gt; (origin type &lt;code&gt;lambda&lt;/code&gt;, signing behavior &lt;code&gt;always-amz-auth&lt;/code&gt;) against an &lt;code&gt;IamAuth&lt;/code&gt; endpoint. CloudFront origin support launched the same day at no extra cost.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdaslzen7g23uhzui7abf.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdaslzen7g23uhzui7abf.webp" alt="CloudFront + WAF in front of an IamAuth Web Function endpoint. Image: AWS documentation" width="799" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outbound VPC access uses a network connector (&lt;code&gt;aws lambda-core create-network-connector&lt;/code&gt;) referenced by version-qualified ARN from the revision. It only works with &lt;code&gt;HomeRegion&lt;/code&gt; endpoints, and you still need a NAT gateway for internet egress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gotchas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Active" doesn't mean "working."&lt;/strong&gt; Lambda doesn't check that your server answers. Always smoke-test after deploying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardcoded ports&lt;/strong&gt; never become ready. Read &lt;code&gt;AWS_LAMBDA_HTTP_ENDPOINT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global mutable state&lt;/strong&gt; is now a concurrency bug, just like in a container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2 GB is shared&lt;/strong&gt; by heap, buffers and every in-flight request. V8's default heap is 1,024 MB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS is cached&lt;/strong&gt; per environment; ship a new revision after private DNS changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signed requests&lt;/strong&gt; to &lt;code&gt;IamAuth&lt;/code&gt; endpoints must include &lt;code&gt;X-Amz-Content-SHA256&lt;/code&gt;, even with no body.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;delete-web-function&lt;/code&gt; leaves the default IAM role, S3 packages and log groups behind.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pricing, honestly
&lt;/h2&gt;

&lt;p&gt;AWS's own examples assume one environment for a 30-day month: an SSR app with 15M requests costs $25.78; an I/O-heavy API with 10M requests (200 ms, 50 ms CPU) costs $19.61; an LLM streaming endpoint with 5M requests of 3 s (200 ms CPU) costs $33.94.&lt;/p&gt;

&lt;p&gt;I ran the same workloads through Event Function pricing (x86 rate listed on the same page, my assumption of 512 MB, no free tier): roughly $18.67 for the I/O API, $21.75 for SSR, and &lt;strong&gt;about $126 for LLM streaming&lt;/strong&gt;. So Web Functions isn't automatically cheaper for short requests (the vCPU-second rate is high and requests cost 50% more), but for long, I/O-bound requests like token streaming it's a different order of magnitude.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh77buaxo25ozrgkdjey4.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh77buaxo25ozrgkdjey4.webp" alt="What gets billed in a 200 ms request" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What to check before adopting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regions:&lt;/strong&gt; five at launch, no South America. For users in Argentina or Brazil, us-east-1 is the closest option.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data residency:&lt;/strong&gt; multi-Region endpoints replicate code, and request metrics and logs are centralized asynchronously in the home Region.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Region data transfer:&lt;/strong&gt; a global endpoint serving from Tokyo but querying a database in Virginia pays in latency and transfer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maturity:&lt;/strong&gt; one runtime, brand-new APIs, IaC tooling still catching up. LocalStack 2026.10.0 already emulates it for local testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;The interesting part isn't "Express on Lambda"; we could already do that. It's that AWS changed both the billing unit and the isolation unit of its most used serverless service. For ten years Lambda made us think in one request per environment and pay for waiting time. That made sense for short event handlers and stopped making sense for apps that spend seconds waiting on a model. Web Functions brings Lambda close to a well-scaled container, without a cluster, and with revisions, canaries and multi-Region built in. The weak spots are the launch scope: Node.js only and five Regions. I'd try it now on a non-critical Node.js service, especially one that talks to Bedrock, and wait for the runtime and Region roadmap before making it a platform standard.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published in Spanish on &lt;a href="https://blog.cloudacademy.ar/lambda-web-functions-servidor-http-en-lambda-cpu-activa/" rel="noopener noreferrer"&gt;CloudAcademy.ar&lt;/a&gt;, with the full CLI walkthrough, VPC connector setup and SCP.&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/10/aws-lambda-web-functions/" rel="noopener noreferrer"&gt;What's New: AWS Lambda announces Lambda Web Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/aws/announcing-aws-lambda-web-functions-for-fast-consistent-web-app-performance-anywhere/" rel="noopener noreferrer"&gt;AWS News Blog announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/10/cloudfront-lambda-web-functions-origin/" rel="noopener noreferrer"&gt;CloudFront supports Lambda Web Functions as an origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/web-functions.html" rel="noopener noreferrer"&gt;Lambda Web Functions developer guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/web-functions-scaling.html" rel="noopener noreferrer"&gt;Scaling behavior and quotas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/web-functions-endpoint-access-control.html" rel="noopener noreferrer"&gt;Endpoint access control&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/lambda/pricing/" rel="noopener noreferrer"&gt;AWS Lambda pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.localstack.cloud/aws-lambda-web-functions-are-here/" rel="noopener noreferrer"&gt;LocalStack: test Web Functions locally&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>lambda</category>
      <category>node</category>
    </item>
    <item>
      <title>AWS Well-Architected Agent: Your Architecture Review, Now Done by an Agent (Preview)</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 12:55:30 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/aws-well-architected-agent-your-architecture-review-now-done-by-an-agent-preview-4k3m</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/aws-well-architected-agent-your-architecture-review-now-done-by-an-agent-preview-4k3m</guid>
      <description>&lt;p&gt;A proper Well-Architected review has always had the same cost: a day or two of the team answering a long questionnaire, someone pulling evidence from five consoles, and a report that's stale within weeks. Trusted Advisor helps with point checks, but it has no idea which application matters or what your business is optimizing for this quarter.&lt;/p&gt;

&lt;p&gt;On October 1, 2026, AWS launched &lt;strong&gt;AWS Well-Architected Agent&lt;/strong&gt; in public preview. It continuously analyzes your accounts and returns cost, security, resilience, and performance recommendations ranked against goals you write yourself, and it hands you the fix: console steps, CLI commands, or the change to your infrastructure code. AWS positions it as the next step after Trusted Advisor and the Well-Architected Tool, delivered through AWS Support.&lt;/p&gt;

&lt;p&gt;Here's how it works, how to wire it up with read-only cross-account roles, how to point it at an EKS Terraform repo before you deploy, and what to check before granting it access to your whole organization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm9njki004anasai8zbk1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm9njki004anasai8zbk1.webp" alt="How AWS Well-Architected Agent works: profile, read-only access, analysis, recommendations" width="800" height="390"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Profile → read-only role chaining → analysis → recommendations with remediation. (Diagram labels in Spanish, from the original article.)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Public preview since Oct 1, 2026. The service runs in us-east-1, us-east-2, and us-west-2, but can analyze resources in &lt;strong&gt;any commercial Region&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You create a &lt;strong&gt;profile&lt;/strong&gt;: up to 100 accounts, their Regions, the pillars you care about, and a goal per pillar. First recommendations land within 24 hours.&lt;/li&gt;
&lt;li&gt;It reads resource configuration across 65+ services, utilization metrics, and application topology via &lt;strong&gt;read-only&lt;/strong&gt; roles.&lt;/li&gt;
&lt;li&gt;Recommendations come at three levels (resource, application, architecture) with priority, effort, impact, ROI, and explicit trade-offs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IaC review&lt;/strong&gt;: upload a .zip of Terraform, CloudFormation, or CDK and get findings before anything is deployed.&lt;/li&gt;
&lt;li&gt;Remediation via console, updated IaC, CLI, SDK, SSM runbooks, and MCP. In what AWS showed, it doesn't change resources on its own.&lt;/li&gt;
&lt;li&gt;Requires an AWS Support plan. No published preview pricing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What it is (and isn't)
&lt;/h2&gt;

&lt;p&gt;It's an AWS Support service surfaced in the Well-Architected console. It doesn't replace the Well-Architected Tool (AWS says you can keep using it for manual reviews), it isn't a compliance auditor, and every recommendation carries a disclaimer that it's AI-generated and may be wrong or incomplete.&lt;/p&gt;

&lt;p&gt;Preview scope: the console offers four pillars (cost, security, resilience, performance). The API already lists &lt;code&gt;OPERATIONAL_EXCELLENCE&lt;/code&gt; as a value, but it isn't exposed in the preview console. IaC reviews currently use the Well-Architected Framework lens.&lt;/p&gt;
&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Profile.&lt;/strong&gt; Created in a host account. You list target accounts (up to 100) and Regions, choose pillars, write a goal for each ("reduce unnecessary spend across my accounts", "workloads recover gracefully from disruptions"), and pick the execution role. Deletion protection is on by default in the console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vo5acemq497ts7ljr2e.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7vo5acemq497ts7ljr2e.webp" alt="Creating a Well-Architected Agent profile in the console" width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Profile setup: Regions, accounts, pillars with goals, roles. Image: AWS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application context&lt;/strong&gt; (optional). Tell it which applications exist, where they live, and which tags identify them. That's what turns "15 queues without alarms" into "your event pipeline has no failure observability in any of its three Regions."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access.&lt;/strong&gt; Role chaining: an execution role in the profile account trusts &lt;code&gt;wellarchitected.amazonaws.com&lt;/code&gt; and can assume an access role in each target account; access roles use the managed policy &lt;code&gt;WellArchitectedAgentResourceScanning&lt;/code&gt; and trust the execution role, with the profile ARN as external ID to prevent confused-deputy issues. Onboarding is opt-in per account.&lt;/p&gt;
&lt;h2&gt;
  
  
  Recommendations and remediation
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;AWS example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Resource&lt;/td&gt;
&lt;td&gt;One resource or a small group&lt;/td&gt;
&lt;td&gt;CloudFormation role with &lt;code&gt;Action: "*"&lt;/code&gt; on &lt;code&gt;Resource: "*"&lt;/code&gt; that only needs 7 service namespaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application (beta)&lt;/td&gt;
&lt;td&gt;Findings across one app&lt;/td&gt;
&lt;td&gt;15 DLQs in three Regions with no alarms; 48-minute median time to detect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture&lt;/td&gt;
&lt;td&gt;Patterns and IaC changes&lt;/td&gt;
&lt;td&gt;ECS Fargate tasks ~2x over-provisioned based on 30-day p95 CPU/memory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each comes with priority, effort, impact, an ROI estimate, affected resources, cross-pillar benefits, and &lt;strong&gt;trade-offs&lt;/strong&gt;. That last field is what a good architect always tells you, and here it's explicit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5dyyj9cug96ohz1g1rrk.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5dyyj9cug96ohz1g1rrk.webp" alt="Well-Architected Agent dashboard with prioritized recommendations" width="800" height="930"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Recommendations ranked against the profile's goals. Image: AWS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start remediation&lt;/strong&gt; lets you pick console, updated IaC template, or AWS CLI. The API's remediation types also include SDK, MCP, and &lt;code&gt;AUTO_REMEDIATION&lt;/code&gt;. In AWS's example, the IaC option returns a CDK helper ready to paste into your stack, split into phases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjbtmm9gtmo8wilzoxho.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjbtmm9gtmo8wilzoxho.webp" alt="Remediation options with updated IaC (CDK) code" width="799" height="648"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;IaC remediation returns the change for your repo. Image: AWS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture review.&lt;/strong&gt; Upload a .zip of your IaC project to S3, choose lens and pillars, start the review. Binary and media files are excluded. Classmethod tried it on day one: the review took about 30 minutes and flagged, among other things, a Lambda function hard-coded to &lt;code&gt;MemorySize: 256&lt;/code&gt; with no alarms or tuning automation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hands-on
&lt;/h2&gt;

&lt;p&gt;You need an active AWS Support plan, a recent AWS CLI, and one of the service Regions (us-east-1 here).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Execution role&lt;/strong&gt; (profile account):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; exec-trust.json &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
{"Version":"2012-10-17","Statement":[{"Effect":"Allow",
 "Principal":{"Service":"wellarchitected.amazonaws.com"},"Action":"sts:AssumeRole"}]}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;aws iam create-role &lt;span class="nt"&gt;--path&lt;/span&gt; /service-role/ &lt;span class="nt"&gt;--role-name&lt;/span&gt; WAAgentExecutionRole &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--assume-role-policy-document&lt;/span&gt; file://exec-trust.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give it &lt;code&gt;sts:AssumeRole&lt;/code&gt; on &lt;code&gt;arn:aws:iam::*:role/AccessRoleForWellArchitectedAgent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Access role&lt;/strong&gt; (each target account). Look up the managed policy ARN instead of hard-coding it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;POLICY_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws iam list-policies &lt;span class="nt"&gt;--scope&lt;/span&gt; AWS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Policies[?PolicyName=='WellArchitectedAgentResourceScanning'].Arn"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
aws iam create-role &lt;span class="nt"&gt;--role-name&lt;/span&gt; AccessRoleForWellArchitectedAgent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--assume-role-policy-document&lt;/span&gt; file://access-trust.json
aws iam attach-role-policy &lt;span class="nt"&gt;--role-name&lt;/span&gt; AccessRoleForWellArchitectedAgent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$POLICY_ARN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At scale, deploy this with CloudFormation StackSets, and add the external ID condition per the IAM docs once the profile exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Profile:&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 wellarchitected create-agent-profile &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; platform-eks &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--business-overview&lt;/span&gt; &lt;span class="s2"&gt;"EKS container platform for payment APIs"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pillars&lt;/span&gt; COST_OPTIMIZATION SECURITY RESILIENCE PERFORMANCE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--execution-role-arn&lt;/span&gt; arn:aws:iam::111122223333:role/service-role/WAAgentExecutionRole &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--aggregation-configuration&lt;/span&gt; file://aggregation.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--deletion-protection&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;aggregation.json&lt;/code&gt; is a list of &lt;code&gt;{"accountId", "regions", "accessRoleArn"}&lt;/code&gt; objects. &lt;code&gt;get-agent-profile&lt;/code&gt; reports &lt;code&gt;eligibleForScheduledGeneration&lt;/code&gt;, &lt;code&gt;eligibleForArchitectureGeneration&lt;/code&gt;, and any &lt;code&gt;fieldErrors&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Review an EKS Terraform repo&lt;/strong&gt; — package it without state, provider cache, or secrets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zip &lt;span class="nt"&gt;-r&lt;/span&gt; ../infra-eks.zip &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s2"&gt;".terraform/*"&lt;/span&gt; &lt;span class="s2"&gt;"*.tfstate"&lt;/span&gt; &lt;span class="s2"&gt;"*.tfstate.backup"&lt;/span&gt; &lt;span class="s2"&gt;"*.tfvars"&lt;/span&gt; &lt;span class="s2"&gt;".git/*"&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;cp&lt;/span&gt; ../infra-eks.zip s3://my-review-bucket/infra-eks.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;strong&gt;Conduct architecture review&lt;/strong&gt; in the console.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Pull recommendations from the CLI:&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 wellarchitected list-agent-recommendations &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--profile-arn&lt;/span&gt; arn:aws:wellarchitected:us-east-1:111122223333:agent-profile/platform-eks &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pillar&lt;/span&gt; COST_OPTIMIZATION &lt;span class="nt"&gt;--state&lt;/span&gt; OPEN &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

aws wellarchitected get-agent-recommendation &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--recommendation-arn&lt;/span&gt; &amp;lt;recommendation ARN&amp;gt; &lt;span class="nt"&gt;--remediation-type&lt;/span&gt; IAC &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each recommendation includes &lt;code&gt;awsServices&lt;/code&gt;, so you can filter EKS/ECS items into a weekly platform report or open an issue per &lt;code&gt;HIGH&lt;/code&gt; finding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traps:&lt;/strong&gt; applying CLI fixes in a GitOps setup (Terraform or Argo CD will revert the drift; route IaC fixes through PRs); zipping &lt;code&gt;tfvars&lt;/code&gt; or &lt;code&gt;.env&lt;/code&gt; files; assuming read-only means nothing sensitive is read; expecting results before 24 hours; treating dollar figures as exact; forgetting deletion protection when you try to remove a profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing and availability
&lt;/h2&gt;

&lt;p&gt;No published price during preview; it requires an active AWS Support plan. You pay normally for the S3 object holding your IaC zip and for whatever remediation deploys (alarms, SSM runbooks, capacity changes).&lt;/p&gt;

&lt;p&gt;The service runs only in three US Regions but can onboard resources from any commercial Region. That's the part to check: if your workloads live in, say, São Paulo, their configuration, metrics, and uploaded IaC get processed in the US, and the announcement doesn't say where that data is stored or for how long. Regulated workloads should get a compliance sign-off first. And it's a preview, so APIs, pillars, lenses, and pricing can change.&lt;/p&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;What matters here isn't that it uses AI. It's that the unit of work changes. Trusted Advisor gave you checks; the Well-Architected Tool gave you a questionnaire. This gives you a recommendation with context, impact, trade-offs, and the change for your repo, ranked by goals you wrote. If quality holds up in messy real environments (AWS's demo was very polished; Classmethod got reasonable but medium/low-priority findings), it'll replace most annual manual reviews. Two things are still unknown: price and data residency. I'd try it now on non-production accounts, route every fix through a pull request, and wait for GA pricing before rolling it out org-wide.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/aws/announcing-aws-well-architected-agent-an-ai-powered-intelligence-to-optimize-your-cloud-environment-preview/" rel="noopener noreferrer"&gt;AWS News Blog announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/10/aws-well-architected-agent/" rel="noopener noreferrer"&gt;What's New&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/userguide/wa-agent.html" rel="noopener noreferrer"&gt;User guide&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/userguide/security-iam-agent.html" rel="noopener noreferrer"&gt;IAM for the agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CLI: &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/wellarchitected/create-agent-profile.html" rel="noopener noreferrer"&gt;create-agent-profile&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/wellarchitected/list-agent-recommendations.html" rel="noopener noreferrer"&gt;list-agent-recommendations&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/wellarchitected/get-agent-recommendation.html" rel="noopener noreferrer"&gt;get-agent-recommendation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.classmethod.jp/articles/aws-wa-agent-preview/" rel="noopener noreferrer"&gt;Classmethod hands-on (Japanese)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published in Spanish on &lt;a href="https://blog.cloudacademy.ar/aws-well-architected-agent-preview/" rel="noopener noreferrer"&gt;CloudAcademy.ar&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>ai</category>
      <category>cloud</category>
    </item>
    <item>
      <title>S3 Vectors Now Filters Before It Searches: Metadata Pre-Filtering for Multi-Tenant RAG</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 12:55:30 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/s3-vectors-now-filters-before-it-searches-metadata-pre-filtering-for-multi-tenant-rag-5eaj</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/s3-vectors-now-filters-before-it-searches-metadata-pre-filtering-for-multi-tenant-rag-5eaj</guid>
      <description>&lt;p&gt;If you run RAG on Amazon S3 Vectors with metadata filters, you may have been losing results without knowing it. Ask for the 10 nearest chunks &lt;em&gt;for one tenant&lt;/em&gt; and you might get 3 back, or 10 that aren't actually the closest ones in that tenant's data. No error, no alarm, just a model answering with less context than it should have had.&lt;/p&gt;

&lt;p&gt;On September 30, 2026, AWS shipped &lt;strong&gt;metadata pre-filtering&lt;/strong&gt; for S3 Vectors. Indexes now come in two modes, and the new one evaluates your filter &lt;em&gt;before&lt;/em&gt; the similarity search instead of during it. AWS says that returns up to 5x more matching vectors when the filter is selective. It also adds a &lt;code&gt;$startsWith&lt;/code&gt; prefix operator, sets a 100-condition limit per query, and costs nothing extra.&lt;/p&gt;

&lt;p&gt;Here's what changed, why the old behavior dropped results, how to measure the difference on your own index, and what a multi-tenant retrieval service on Amazon EKS looks like with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbcggf908p08c8landog5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbcggf908p08c8landog5.webp" alt="Diagram comparing CLASSIC and ENHANCED query processing in S3 Vectors" width="800" height="350"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;CLASSIC validates the filter while searching; ENHANCED narrows the set first. (Diagram labels in Spanish, from the original article.)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;S3 Vectors indexes now have a mode: &lt;code&gt;CLASSIC&lt;/code&gt; (filter evaluated in tandem with the approximate search) or &lt;code&gt;ENHANCED&lt;/code&gt; (filter resolved first, then similarity search over the matching subset).&lt;/li&gt;
&lt;li&gt;With selective filters, &lt;code&gt;ENHANCED&lt;/code&gt; returns up to 5x more matching vectors, per AWS.&lt;/li&gt;
&lt;li&gt;Vector buckets created on or after Sep 30, 2026 are &lt;code&gt;ENHANCED&lt;/code&gt;-only. Older buckets stay &lt;code&gt;CLASSIC&lt;/code&gt; until you run &lt;code&gt;UpdateIndexMode&lt;/code&gt;; no re-ingestion needed.&lt;/li&gt;
&lt;li&gt;You can test per query with &lt;code&gt;queryMode=ENHANCED&lt;/code&gt; before switching the index.&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;$startsWith&lt;/code&gt; operator; &lt;code&gt;ENHANCED&lt;/code&gt; indexes cap filters at 100 conditions (each &lt;code&gt;$in&lt;/code&gt; value counts).&lt;/li&gt;
&lt;li&gt;No additional cost. Available in every commercial Region with S3 Vectors, including São Paulo, plus the China Regions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why the old mode lost results
&lt;/h2&gt;

&lt;p&gt;Vector search at scale is approximate: the engine explores a neighborhood of promising candidates on a bounded budget rather than comparing your query against every vector.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;CLASSIC&lt;/code&gt; mode, filters are checked &lt;em&gt;while&lt;/em&gt; that exploration runs. If your filter matches half the corpus, most candidates pass and nothing bad happens. If it matches 0.005%, almost every candidate gets thrown away, the budget runs out, and you get fewer than K results, or K results that aren't the true nearest neighbors within the filtered set. The docs say it plainly: in &lt;code&gt;CLASSIC&lt;/code&gt;, filtered queries may return fewer than K results when few vectors match.&lt;/p&gt;

&lt;p&gt;An AWS re:Post article measured this on one million synthetic vectors: recall@10 went from 0.86 unfiltered to 0.83 at 10% selectivity, 0.42 at 1%, and 0.15 at 0.01%. The workaround was to partition data into separate indexes by low-cardinality fields (tenant, language, Region), which recovered 15–31 recall points at the cost of managing more indexes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ENHANCED&lt;/code&gt; flips the order. AWS's example: 8 million support tickets, one customer owns 400. With pre-filtering, the similarity search runs over those 400, not over candidates drawn from all 8 million.&lt;/p&gt;

&lt;p&gt;One takeaway worth repeating: &lt;strong&gt;result count is not a quality signal&lt;/strong&gt;. Getting 10 results back in &lt;code&gt;CLASSIC&lt;/code&gt; never guaranteed they were the best 10.&lt;/p&gt;
&lt;h2&gt;
  
  
  Index modes at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Default mode&lt;/th&gt;
&lt;th&gt;Can you change it?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Buckets created on/after Sep 30, 2026&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ENHANCED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No way back to &lt;code&gt;CLASSIC&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Buckets created before Sep 30, 2026&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLASSIC&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes: to &lt;code&gt;ENHANCED&lt;/code&gt; via &lt;code&gt;UpdateIndexMode&lt;/code&gt;, and back to &lt;code&gt;CLASSIC&lt;/code&gt; via CLI/SDK/API only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New indexes in an older bucket&lt;/td&gt;
&lt;td&gt;Bucket default&lt;/td&gt;
&lt;td&gt;Set with &lt;code&gt;PutVectorBucketDefaultIndexMode&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;UpdateIndexMode&lt;/code&gt; affects only that index. The console offers &lt;strong&gt;Enable enhanced index mode&lt;/strong&gt; on the index detail page; reverting is not available in the console. The current mode shows up as &lt;code&gt;indexMode&lt;/code&gt; in &lt;code&gt;GetIndex&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Filters: operators and the 100-condition limit
&lt;/h2&gt;

&lt;p&gt;Filter syntax is unchanged: &lt;code&gt;$eq&lt;/code&gt;, &lt;code&gt;$ne&lt;/code&gt;, &lt;code&gt;$gt&lt;/code&gt;, &lt;code&gt;$gte&lt;/code&gt;, &lt;code&gt;$lt&lt;/code&gt;, &lt;code&gt;$lte&lt;/code&gt;, &lt;code&gt;$in&lt;/code&gt;, &lt;code&gt;$nin&lt;/code&gt;, &lt;code&gt;$exists&lt;/code&gt;, &lt;code&gt;$and&lt;/code&gt;, &lt;code&gt;$or&lt;/code&gt;, plus the new &lt;code&gt;$startsWith&lt;/code&gt; (string prefix, &lt;code&gt;ENHANCED&lt;/code&gt; only). Prefix matching is handy for path-organized collections: &lt;code&gt;{"s3_path": {"$startsWith": "matter-4417/exhibits/"}}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The 100-condition cap applies to &lt;code&gt;ENHANCED&lt;/code&gt; indexes and is counted per value: &lt;code&gt;{"region": {"$in": ["us-east-1", "us-west-2", "eu-west-1"]}}&lt;/code&gt; is 3 conditions. If you build dynamic filters with long &lt;code&gt;$in&lt;/code&gt; lists (say, every project a user can access), audit them before migrating: over 100, an &lt;code&gt;ENHANCED&lt;/code&gt; index returns a validation error.&lt;/p&gt;

&lt;p&gt;Metadata limits haven't changed: up to 40 KB per vector, of which up to 2 KB is filterable; up to 50 keys; up to 10 non-filterable keys per index, fixed at index creation. Keep filter fields short and put chunk text in non-filterable metadata. Bedrock Knowledge Bases already does this with &lt;code&gt;AMAZON_BEDROCK_TEXT&lt;/code&gt; and &lt;code&gt;AMAZON_BEDROCK_METADATA&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq2u6skyi8rux3zrea385.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq2u6skyi8rux3zrea385.webp" alt="S3 console index creation form showing non-filterable metadata keys" width="800" height="508"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Non-filterable keys are declared at index creation and can't be changed later. Image: AWS.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hands-on
&lt;/h2&gt;

&lt;p&gt;You'll need a recent AWS CLI and boto3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Check the mode&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 s3vectors get-index &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vector-bucket-name&lt;/span&gt; my-vector-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--index-name&lt;/span&gt; tickets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'index.indexMode'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Measure recall before migrating.&lt;/strong&gt; Pick a small tenant, compute its true top-K by brute force, and compare against the index in each mode. This reads the whole index with &lt;code&gt;ListVectors&lt;/code&gt;, so do it on a test copy or a sample.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="n"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;INDEX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TENANT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-vector-bucket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tickets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;t-10428&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;s3v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3vectors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bedrock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock-runtime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inputText&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dimensions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;normalize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bedrock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amazon.titan-embed-text-v2:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;kw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorBucketName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indexName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;INDEX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maxResults&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="n"&gt;returnData&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;returnMetadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;kw&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nextToken&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
    &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_vectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vectors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tenant_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;TENANT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="n"&gt;mat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;float32&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nextToken&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="n"&gt;mat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ground_truth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mat&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;argsort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sims&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query_vectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorBucketName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indexName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;INDEX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;queryVector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;float32&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;topK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tenant_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TENANT&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;queryMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vectors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t log in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;billing error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan change&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;gt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ground_truth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLASSIC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ENHANCED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; returned=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;got&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; recall@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;got&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This assumes cosine distance and 1024-dim Titan Text Embeddings V2; adjust to your index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Migrate&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 s3vectors update-index-mode &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vector-bucket-name&lt;/span&gt; my-vector-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--index-name&lt;/span&gt; tickets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--index-mode&lt;/span&gt; ENHANCED

aws s3vectors put-vector-bucket-default-index-mode &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vector-bucket-name&lt;/span&gt; my-vector-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--default-index-mode&lt;/span&gt; ENHANCED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Retrieval on EKS with Pod Identity.&lt;/strong&gt; The tenant ID comes from the user's token, never from a client-controlled parameter. The API builds the filter; the pod queries S3 Vectors with a role scoped to one index.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqq638aoz6wxjz22udgad.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqq638aoz6wxjz22udgad.webp" alt="Multi-tenant retrieval architecture on Amazon EKS querying an ENHANCED S3 Vectors index" width="800" height="380"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The tenant filter is built server-side and resolved before the similarity search. (Diagram labels in Spanish.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A permissions gotcha: &lt;code&gt;s3vectors:QueryVectors&lt;/code&gt; alone only works without filters and without &lt;code&gt;returnMetadata&lt;/code&gt;. With either, you also need &lt;code&gt;s3vectors:GetVectors&lt;/code&gt;, or you get a 403.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"s3vectors:QueryVectors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3vectors:GetVectors"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3vectors:sa-east-1:111122223333:bucket/my-vector-bucket/index/tickets"&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;Trust policy principal is &lt;code&gt;pods.eks.amazonaws.com&lt;/code&gt; with &lt;code&gt;sts:AssumeRole&lt;/code&gt; and &lt;code&gt;sts:TagSession&lt;/code&gt;, and the cluster needs the &lt;code&gt;eks-pod-identity-agent&lt;/code&gt; add-on. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eks create-pod-identity-association &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; my-cluster &lt;span class="nt"&gt;--namespace&lt;/span&gt; rag &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--service-account&lt;/span&gt; retrieval &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-arn&lt;/span&gt; arn:aws:iam::111122223333:role/rag-retrieval
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the search function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="n"&gt;s3v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3vectors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;conds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tenant_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$startsWith&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query_vectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;vectorBucketName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VECTOR_BUCKET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;indexName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VECTOR_INDEX&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;queryVector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;float32&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;topK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$and&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;conds&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;returnMetadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;returnDistance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vectors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Common traps:&lt;/strong&gt; treating a tenant filter as isolation (a bug that drops it exposes the whole index; use per-tenant indexes with separate IAM for strict isolation); exceeding 100 conditions; using &lt;code&gt;$startsWith&lt;/code&gt; on a &lt;code&gt;CLASSIC&lt;/code&gt; index without &lt;code&gt;queryMode=ENHANCED&lt;/code&gt;; storing dates as strings (range operators are numeric only); and skipping latency tests with broad filters, since AWS notes latency grows with index size, filter breadth, and condition count.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;No extra charge for pre-filtering. S3 Vectors pricing in us-east-1: storage $0.06/GB-month; PUT $0.20/GB uploaded; $2.50 per million query API calls; plus per-TB data-processed charges tiered by index size, and the first 512 KB returned per query free. AWS's published example (10M 1024-dim vectors across 40 indexes, 1M queries/month at top-100) comes to &lt;strong&gt;$11.38/month&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Note from that example: processing is driven by the size of the index you query, not by how many vectors pass the filter. A selective filter improves recall but doesn't make the query cheaper. Large tenants that always query their own data are still good candidates for a dedicated index.&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability and caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regions:&lt;/strong&gt; all commercial Regions where S3 Vectors runs (including sa-east-1) and the China Regions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data residency:&lt;/strong&gt; vectors stay in the bucket's Region; check where your embedding model runs, especially with cross-Region inference profiles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Region traffic:&lt;/strong&gt; keep your compute and your vector bucket in the same Region.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bedrock Knowledge Bases:&lt;/strong&gt; the announcement doesn't detail how &lt;code&gt;Retrieve&lt;/code&gt; filters interact with index mode. If your knowledge base sits on a pre-Sep 30 bucket, check the index mode and measure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;This fixes a limitation that forced you to design around the engine instead of the problem. Until now, the honest answer to "can all my tenants share one index?" was "yes, but small tenants will lose results." With pre-filtering, a shared index becomes reasonable for the long tail, while large tenants or those needing strict IAM isolation keep dedicated indexes. What doesn't change: the filter is still your code, and in multi-tenant RAG a missing filter is a data leak. I'd run the recall test above, migrate &lt;code&gt;CLASSIC&lt;/code&gt; indexes, and use the occasion to audit where tenant filters get built.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/09/s3-vectors-introduces-metadata-pre-filtering/" rel="noopener noreferrer"&gt;What's New: S3 Vectors introduces metadata pre-filtering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/aws/amazon-s3-vectors-now-supports-metadata-pre-filtering-for-higher-recall-on-filtered-searches/" rel="noopener noreferrer"&gt;AWS News Blog announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-metadata-filtering.html" rel="noopener noreferrer"&gt;Docs: Metadata filtering&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-index-mode.html" rel="noopener noreferrer"&gt;Changing index mode&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-limitations.html" rel="noopener noreferrer"&gt;Limits&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/s3/pricing/" rel="noopener noreferrer"&gt;S3 pricing (S3 Vectors tab)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://repost.aws/articles/ARpXgjTc00RZG4mfUYQ7Y-QQ/how-metadata-filter-selectivity-affects-recall-in-amazon-s3-vectors" rel="noopener noreferrer"&gt;re:Post: How metadata filter selectivity affects recall in S3 Vectors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published in Spanish on &lt;a href="https://blog.cloudacademy.ar/s3-vectors-pre-filtrado-de-metadata-rag-multi-tenant/" rel="noopener noreferrer"&gt;CloudAcademy.ar&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>rag</category>
      <category>kubernetes</category>
      <category>ai</category>
    </item>
    <item>
      <title>EventBridge's new custom event bus: one bus for the whole org, with ordering, replay and per-GB pricing</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Mon, 28 Sep 2026 15:21:00 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/eventbridges-new-custom-event-bus-one-bus-for-the-whole-org-with-ordering-replay-and-per-gb-3k2g</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/eventbridges-new-custom-event-bus-one-bus-for-the-whole-org-with-ordering-replay-and-per-gb-3k2g</guid>
      <description>&lt;p&gt;On September 24, 2026, AWS relaunched the Amazon EventBridge custom event bus. This isn't a new toggle on the bus you already know. It's a separate resource with its own API namespace (&lt;code&gt;eventsv2&lt;/code&gt;), its own sharing model, and a pricing model based on data volume instead of event count. Your existing buses are renamed "Custom event bus – classic" and keep working exactly as before.&lt;/p&gt;

&lt;p&gt;The interesting part is what AWS is going after. EventBridge has always been pleasant inside a single account, but in a multi-account organization you end up with a mesh of buses, forwarding rules and resource policies, and the platform team becomes the ticket queue for every new subscription. And the moment someone needs strict ordering or wants to reprocess last Tuesday's events, the answer used to be "put SQS FIFO, Kinesis or Kafka in the middle."&lt;/p&gt;

&lt;p&gt;The new bus tackles both problems: one bus shared across the organization, per-group FIFO delivery, deduplication, retention of up to a year, and replay from any point in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;New &lt;strong&gt;custom event bus&lt;/strong&gt; resource (&lt;code&gt;eventsv2&lt;/code&gt; API). The old one becomes &lt;em&gt;classic&lt;/em&gt; and doesn't change.&lt;/li&gt;
&lt;li&gt;Share one bus with accounts, OUs or the whole organization through &lt;strong&gt;AWS RAM&lt;/strong&gt; using four managed permissions. Default quota: 10,000 subscribers per bus.&lt;/li&gt;
&lt;li&gt;New &lt;strong&gt;Subscriber&lt;/strong&gt; resource: filter + transformation + one target + retries + DLQ, owned by each consuming account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FIFO per &lt;code&gt;EventGroupId&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;deduplication&lt;/strong&gt; within a 5-minute window, &lt;strong&gt;retention&lt;/strong&gt; from 1 to 365 days, &lt;strong&gt;replay&lt;/strong&gt; via each subscriber's starting position.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PutRawEvents&lt;/code&gt; accepts JSON, Avro, Protobuf or raw bytes with custom metadata. Transformations are written in &lt;strong&gt;JSONata&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pricing: $0.18/GB ingress ($0.12 after 5,000 GB), $0.05/GB egress per subscriber, $0.08/GB-month extra retention, $0.15 per million evaluations.&lt;/li&gt;
&lt;li&gt;14 Regions at launch. &lt;strong&gt;Not in São Paulo (sa-east-1)&lt;/strong&gt; yet.&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F06z9tqqd09oe0y5ldq1e.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F06z9tqqd09oe0y5ldq1e.webp" alt="A shared bus in the platform account with publishing accounts on the left and team accounts owning their subscribers on the right" width="800" height="430"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;One bus in the platform account, shared via AWS RAM. Each team creates, and pays for, its own subscribers.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The ownership model is the real change
&lt;/h2&gt;

&lt;p&gt;The classic model has the bus owner writing rules on behalf of everyone. In the new model, the platform team creates the bus and shares it; each team creates subscribers in its own account, only sees its own subscribers when listing, and can't modify or delete the bus. The owner sees every subscriber and can cut one off with &lt;code&gt;RevokeResource&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sharing uses four RAM managed permissions: &lt;code&gt;AWSRAMEventBridgeEventBusV2PublishOnly&lt;/code&gt;, &lt;code&gt;...SubscribeOnly&lt;/code&gt;, &lt;code&gt;...EventSourceAccess&lt;/code&gt; and &lt;code&gt;...FullAccess&lt;/code&gt;. Two constraints to design around: consumers can't re-share the bus, and &lt;strong&gt;the bus and its subscribers must live in the same Region and partition&lt;/strong&gt;. Sharing is free, and the owner gets per-consumer &lt;code&gt;EventsDelivered&lt;/code&gt; and &lt;code&gt;EgressBytes&lt;/code&gt; metrics, which is handy for chargeback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5sv780ono7mvkfxz7nsu.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5sv780ono7mvkfxz7nsu.webp" alt="EventBridge console showing the new and classic custom event bus options" width="800" height="630"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Creating a custom event bus: new vs. classic. Image: AWS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxic2o00152msko18f4jg.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxic2o00152msko18f4jg.webp" alt="Sharing the bus with AWS Resource Access Manager" width="800" height="362"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Sharing the bus through AWS RAM. Image: AWS.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Subscribers
&lt;/h2&gt;

&lt;p&gt;A subscriber bundles what used to be spread across a rule, its targets, an input transformer, a retry policy and a DLQ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Filters&lt;/strong&gt; use regular event pattern syntax with three scopes: &lt;code&gt;DATA&lt;/code&gt; (payload), &lt;code&gt;METADATA&lt;/code&gt; (producer-supplied key/value pairs, exact match only) and &lt;code&gt;SYSTEM_METADATA&lt;/code&gt; (fields EventBridge sets, such as &lt;code&gt;EventGroupId&lt;/code&gt;). An event must match every filter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformers&lt;/strong&gt;: &lt;code&gt;RAW&lt;/code&gt; (default), &lt;code&gt;WITH_METADATA&lt;/code&gt;, or &lt;code&gt;JSONATA&lt;/code&gt; with the event exposed as &lt;code&gt;$events&lt;/code&gt;. Syntax is validated at creation, but evaluation happens at delivery time, so a bad expression fails deliveries, not deployments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One target per subscriber&lt;/strong&gt;: SQS, Lambda, Kinesis, Step Functions, SNS, HTTP/API destinations, Firehose, another bus, or universal targets like &lt;code&gt;arn:aws:events:::aws-sdk:dynamodb:putItem&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries&lt;/strong&gt;: 5 attempts within 300 seconds by default, configurable up to 185 attempts and 24 hours, then an SQS DLQ.&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmasn4k4aq0hnun0uosuh.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmasn4k4aq0hnun0uosuh.webp" alt="Event lifecycle: publish, deduplicate, store, filter, transform, deliver, retry and DLQ" width="800" height="310"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;What happens to an event on the new bus, per subscriber.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Ordering and deduplication, with the fine print
&lt;/h2&gt;

&lt;p&gt;Producers set &lt;code&gt;SystemMetadata.EventGroupId&lt;/code&gt;. Subscribers configured for ordered delivery get events from the same group in sequence; other subscribers get the same events unordered. For Lambda or Express state machines you can invoke synchronously (&lt;code&gt;REQUEST_RESPONSE&lt;/code&gt;) so EventBridge waits for the result before moving on. Standard state machines don't support that mode.&lt;/p&gt;

&lt;p&gt;The docs are upfront about the tradeoff: &lt;strong&gt;a failing event blocks later events in its group for as long as it's retried.&lt;/strong&gt; Keep the retry window short on ordered subscribers and use a FIFO DLQ, where EventBridge sets &lt;code&gt;MessageGroupId&lt;/code&gt; from the &lt;code&gt;EventGroupId&lt;/code&gt; so failures stay ordered too.&lt;/p&gt;

&lt;p&gt;Deduplication happens at publish time, within 5 minutes, using your &lt;code&gt;DeduplicationId&lt;/code&gt; or a content hash. Duplicates come back as &lt;code&gt;DEDUPLICATED&lt;/code&gt;, which is a success code. AWS frames this as exactly-once semantics; I'd read it more narrowly as protection against producer retries. Your consumers still need to be idempotent.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hands-on
&lt;/h2&gt;

&lt;p&gt;Create a bus with 30 days of retention and a customer managed key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eventsv2 create-event-bus &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; orders &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Order events from the checkout service"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--storage-configuration&lt;/span&gt; &lt;span class="nv"&gt;RetentionPeriodInDays&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--encryption-configuration&lt;/span&gt; &lt;span class="nv"&gt;KmsKeyIdentifier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nv"&gt;team&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for &lt;code&gt;ACTIVE&lt;/code&gt; before publishing. A KMS problem leaves it in &lt;code&gt;CREATE_FAILED&lt;/code&gt;, and all you can do is delete it.&lt;/p&gt;

&lt;p&gt;Share it with a consuming account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ram create-resource-share &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; orders-bus-share &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-arns&lt;/span&gt; arn:aws:events:us-east-1:111122223333:event-busv2/orders/EXAMPLE1234567890abcdef &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--principals&lt;/span&gt; 444455556666 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--permission-arns&lt;/span&gt; arn:aws:ram::aws:permission/AWSRAMEventBridgeEventBusV2SubscribeOnly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the consuming account, create a subscriber for large orders with a DLQ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eventsv2 create-subscriber &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; large-orders &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--event-bus-arn&lt;/span&gt; arn:aws:events:us-east-1:111122223333:event-busv2/orders/EXAMPLE1234567890abcdef &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--filter-configuration&lt;/span&gt; &lt;span class="s1"&gt;'{
        "Filters": [
            { "Scope": "DATA", "Pattern": "{\"detail\":{\"total\":[{\"numeric\":[\"&amp;gt;\",500]}]}}" }
        ]
    }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--invoke-configuration&lt;/span&gt; &lt;span class="s1"&gt;'{
        "TargetArn": "arn:aws:sqs:us-east-1:111122223333:large-orders",
        "RoleArn": "arn:aws:iam::111122223333:role/EventBusDeliveryRole"
    }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--on-failure-configuration&lt;/span&gt; &lt;span class="s1"&gt;'{ "Arn": "arn:aws:sqs:us-east-1:111122223333:large-orders-dlq" }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reprocess from a timestamp by creating a subscriber with &lt;code&gt;--starting-position POINT_IN_TIME&lt;/code&gt; and &lt;code&gt;--point-in-time-configuration '{ "PointType": "TIMESTAMP", "StartingPoint": "2026-09-01T00:00:00Z" }'&lt;/code&gt;. Pause with &lt;code&gt;update-subscriber --state STOPPED&lt;/code&gt;, and resume with &lt;code&gt;--resume-position LAST_PROCESSED&lt;/code&gt; (drain the backlog) or &lt;code&gt;LATEST&lt;/code&gt; (skip it).&lt;/p&gt;

&lt;p&gt;Gotchas worth knowing before your first 2 a.m. page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only one subscriber create/delete runs at a time per bus. Parallel IaC gets &lt;code&gt;ConcurrentModificationException&lt;/code&gt;, so retry or serialize.&lt;/li&gt;
&lt;li&gt;Filters depend on the publish API. A pattern written for the &lt;code&gt;PutEvents&lt;/code&gt; envelope matches nothing when the producer uses &lt;code&gt;PutRawEvents&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;LATEST&lt;/code&gt; subscriber won't see events published before it existed.&lt;/li&gt;
&lt;li&gt;For FIFO targets, derive &lt;code&gt;MessageDeduplicationId&lt;/code&gt; per message with JSONata. A constant value means SQS drops everything after the first message.&lt;/li&gt;
&lt;li&gt;Debug with the &lt;code&gt;AWS/EventsV2&lt;/code&gt; metrics as a funnel: &lt;code&gt;FilterEvaluated&lt;/code&gt; → &lt;code&gt;FilterMatched&lt;/code&gt; → &lt;code&gt;EventsDelivered&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pricing: cheaper, until your events get big
&lt;/h2&gt;

&lt;p&gt;AWS's worked example (1,000 events/s at 2 KB, two subscribers, JSONata plus schema validation, 7-day retention, 1% failures) comes to &lt;strong&gt;$2,317/month&lt;/strong&gt;: $922 ingress, $518 egress, $16 retry egress, $778 evaluation, $83 storage. The math checks out.&lt;/p&gt;

&lt;p&gt;What the announcement doesn't show is the comparison with classic, which charges $1 per million events in 64 KB chunks, delivery within an account free and $1 per million for each cross-account delivery. Same volume (2.592 billion events/month, two subscribers, ingress and egress only):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event size&lt;/th&gt;
&lt;th&gt;New bus&lt;/th&gt;
&lt;th&gt;Classic (same account / 2 cross-account deliveries)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 KB&lt;/td&gt;
&lt;td&gt;~$726&lt;/td&gt;
&lt;td&gt;$2,592 / $7,776&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 KB&lt;/td&gt;
&lt;td&gt;~$1,440&lt;/td&gt;
&lt;td&gt;$2,592 / $7,776&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 KB&lt;/td&gt;
&lt;td&gt;~$6,002&lt;/td&gt;
&lt;td&gt;$2,592 / $7,776&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60 KB&lt;/td&gt;
&lt;td&gt;~$34,514&lt;/td&gt;
&lt;td&gt;$2,592 / $7,776&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;My own math from published prices; excludes retention, retries, evaluation, and classic archives.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Small events crossing accounts get much cheaper. Large events can get several times more expensive, because classic charges the same for 1 KB and 64 KB. Against same-account classic with two subscribers, break-even sits around 4 KB per event. So slim your events (claim-check pattern), consider Avro or Protobuf via &lt;code&gt;PutRawEvents&lt;/code&gt;, be deliberate about paid evaluations, and size retention to what you'll actually replay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability
&lt;/h2&gt;

&lt;p&gt;Launch Regions: N. Virginia, Ohio, Oregon, Ireland, Frankfurt, Stockholm, Spain, Hong Kong, Malaysia, Mumbai, Singapore, Sydney, Thailand and Tokyo. No São Paulo. Because subscribers must be in the bus's Region, South American workloads would need to bridge from a classic bus to a new bus in another Region. That's possible, but it adds latency, inter-Region transfer costs and data residency questions, especially now that the bus stores events.&lt;/p&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;This is the biggest change to EventBridge since it launched, and ownership matters more than ordering here. Letting each team create and pay for subscribers on a bus it doesn't own is what makes a central bus something the platform team operates instead of something it serves by ticket. Per-subscriber replay from built-in retention is the other big win. Before migrating, run your real event sizes through the pricing, understand the per-group blocking on ordered subscribers, and check Region coverage. Start with a new domain, or one that's hurting for ordering or replay, and leave the rest on classic, which isn't going anywhere.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published in Spanish on &lt;a href="https://blog.cloudacademy.ar/eventbridge-nuevo-custom-event-bus-orden-replay-organizacion/" rel="noopener noreferrer"&gt;CloudAcademy.ar&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/aws/introducing-enhanced-custom-event-buses-in-amazon-eventbridge-for-enterprise-scale-event-driven-applications/" rel="noopener noreferrer"&gt;AWS News Blog announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/09/eventbridge-relaunches-custom-event-buses/" rel="noopener noreferrer"&gt;What's New post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-what-is.html" rel="noopener noreferrer"&gt;Custom Event Bus documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-subscribers.html" rel="noopener noreferrer"&gt;Subscribers&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-retry.html" rel="noopener noreferrer"&gt;Retries and ordering&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-replay.html" rel="noopener noreferrer"&gt;Replay&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-sharing.html" rel="noopener noreferrer"&gt;Sharing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/eventbridge/pricing/" rel="noopener noreferrer"&gt;EventBridge pricing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>eventdriven</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Amazon GuardDuty AI-powered investigations: a SOC copilot, not an autopilot</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Mon, 29 Jun 2026 22:51:46 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/amazon-guardduty-ai-powered-investigations-a-soc-copilot-not-an-autopilot-eah</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/amazon-guardduty-ai-powered-investigations-a-soc-copilot-not-an-autopilot-eah</guid>
      <description>&lt;h1&gt;
  
  
  Amazon GuardDuty AI-powered investigations: a useful SOC copilot, not an autopilot
&lt;/h1&gt;

&lt;p&gt;AWS just added a capability that many security teams have been trying to build around GuardDuty for years: a faster way to move from “there is a finding” to “this is probably what happened, here is the evidence, and these are the next actions.” The new feature is called &lt;strong&gt;GuardDuty Investigation&lt;/strong&gt;, and it is now available in preview as &lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/amazon-guardduty/" rel="noopener noreferrer"&gt;AI-powered investigations for Amazon GuardDuty&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That wording matters. GuardDuty has already used machine learning and threat intelligence to detect suspicious behavior across AWS accounts, EC2, EKS, ECS, Lambda, S3, RDS, and other surfaces. This launch is not only about detecting another signal. It is about reducing the investigation tax that comes after the alert.&lt;/p&gt;

&lt;p&gt;If you have operated cloud security at scale, you know the pattern: a finding appears, the analyst checks CloudTrail, IAM context, affected resources, related activity, known indicators, suppression rules, account ownership, and whether the finding is a real incident or just a noisy but expected behavior. That work is valuable, but it is also repetitive. It is exactly where a well-scoped AI assistant can help.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  🔵 What changed
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/amazon-guardduty/" rel="noopener noreferrer"&gt;AWS announcement&lt;/a&gt;, AI-powered investigations automatically analyze GuardDuty findings and AWS accounts to help distinguish true threats from benign findings. The investigation looks at finding context, related activity from the last 90 days, affected resources, and threat indicators. AWS says it uses knowledge graphs and threat intelligence to produce the analysis in minutes.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-investigation.html" rel="noopener noreferrer"&gt;GuardDuty Investigation documentation&lt;/a&gt; gives more detail on the output. Each investigation can produce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a risk level: Info, Low, Medium, High, or Critical;&lt;/li&gt;
&lt;li&gt;a confidence level: Unknown, Low, Medium, or High;&lt;/li&gt;
&lt;li&gt;a summary with key observations;&lt;/li&gt;
&lt;li&gt;investigation details with supporting context;&lt;/li&gt;
&lt;li&gt;recommended actions, including CLI commands;&lt;/li&gt;
&lt;li&gt;MITRE ATT&amp;amp;CK technique classification, using the common security knowledge base for attacker tactics and techniques.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a meaningful step beyond a plain alert. It gives the responder a starting hypothesis and evidence trail. The important part is not that the model “knows security.” The useful part is that GuardDuty already has the AWS-native context and can package that context into a structured investigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔶 Three analysis modes
&lt;/h2&gt;

&lt;p&gt;The preview supports three investigation scopes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding analysis&lt;/strong&gt; focuses on one GuardDuty finding. You provide a 32-character finding ID, and GuardDuty analyzes that specific signal. During preview, AWS says this supports all Extended Threat Detection findings and selected findings from foundational, S3, and Runtime plans.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Account analysis&lt;/strong&gt; looks at the threat posture of one AWS account. This is useful when an account has multiple signals or when the first question is not “is this one finding real?” but “is this account behaving like it is under attack?”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Organization analysis&lt;/strong&gt; lets an administrator analyze organization-wide posture, with a preview limit of up to 100 accounts. This is the most interesting mode for larger AWS environments because cloud incidents rarely respect account boundaries. A compromised principal, suspicious API activity, or lateral movement pattern may only make sense when viewed across accounts.&lt;/p&gt;

&lt;p&gt;That said, the preview limits are real. The documentation states that, during preview, you can initiate up to 10 investigations per account per day, with a total limit of 100 investigations per account. The trigger prompt for API or CLI usage can be up to 2,048 characters. Failed investigations do not count against those quotas.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ How to enable it
&lt;/h2&gt;

&lt;p&gt;You need an active GuardDuty detector in the Region where you want to create investigations, and the investigation feature must be enabled for that detector. In the console, AWS exposes this under &lt;strong&gt;Settings → AI powered investigations - Preview&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From the CLI, the docs show the feature name as &lt;code&gt;AI_ANALYST&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws guardduty update-detector &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--detector-id&lt;/span&gt; 2cb3d4e5f6a7b8c9d0e1f2a3b4c5d6e7 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--features&lt;/span&gt; &lt;span class="s1"&gt;'[{"Name":"AI_ANALYST","Status":"ENABLED"}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your IAM identity also needs the investigation permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"guardduty:CreateInvestigation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"guardduty:GetInvestigation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"guardduty:ListInvestigations"&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;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:guardduty:us-west-2:123456789012:detector/2cb3d4e5f6a7b8c9d0e1f2a3b4c5d6e7"&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;A basic investigation can be started with &lt;code&gt;create-investigation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws guardduty create-investigation &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--detector-id&lt;/span&gt; 2cb3d4e5f6a7b8c9d0e1f2a3b4c5d6e7 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--trigger-prompt&lt;/span&gt; &lt;span class="s2"&gt;"Investigate finding 1ab2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 in account 123456789012"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API is asynchronous. You get an &lt;code&gt;InvestigationId&lt;/code&gt;, then retrieve the result with &lt;code&gt;get-investigation&lt;/code&gt; once it completes.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛡️ Where this helps in practice
&lt;/h2&gt;

&lt;p&gt;The obvious use case is SOC triage. Instead of every finding starting as a blank page, the analyst receives a structured summary with risk, confidence, evidence, and recommended commands. That can cut the first 20–40 minutes of manual digging, especially for teams that already receive more alerts than they can deeply review.&lt;/p&gt;

&lt;p&gt;The second use case is consistency. Different analysts may investigate the same GuardDuty finding differently. A standardized AI-generated package can help normalize the first response: what was checked, why the risk was assigned, which known attack technique may apply, and which resources need attention.&lt;/p&gt;

&lt;p&gt;The third use case is managed security. If you operate AWS Organizations for many teams, account analysis and organization analysis are more interesting than single-finding analysis. They can help a central security team answer “which accounts deserve attention first?” instead of treating every alert as equal.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ What to be careful about
&lt;/h2&gt;

&lt;p&gt;The preview documentation is explicit: investigation recommendations may contain errors or incomplete assessments, and human review is recommended. That is the right mental model. This feature should not auto-remediate production resources without a review gate.&lt;/p&gt;

&lt;p&gt;There is also a data residency detail worth reading carefully. GuardDuty Investigation uses Cross-Region Inference Service. AWS says your data remains stored only in the Region where the investigation request originates, but investigation data and summary results may be processed outside that Region within the supported geography. For many organizations that is acceptable; for regulated environments, it needs review.&lt;/p&gt;

&lt;p&gt;Availability is also limited to 10 commercial Regions in preview: US East (N. Virginia), US East (Ohio), US West (Oregon), Canada (Central), Europe (Frankfurt), Europe (Ireland), Europe (London), Europe (Paris), Europe (Stockholm), and Asia Pacific (Tokyo).&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 What this means for security teams
&lt;/h2&gt;

&lt;p&gt;This is the right direction for cloud security tooling. The value is not “AI replaces the analyst.” The value is that AWS has the telemetry, the resource graph, the threat intelligence, and the service context. If GuardDuty can assemble that into a defensible investigation package, analysts can spend less time collecting facts and more time making decisions.&lt;/p&gt;

&lt;p&gt;I would not wire this directly to remediation on day one. I would start by enabling it in a controlled set of accounts, comparing its summaries against human investigations, measuring time saved, and building a review workflow around the recommendations. If the results are good, the next step is not full autopilot. It is faster triage, better evidence, and cleaner escalation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/amazon-guardduty/" rel="noopener noreferrer"&gt;AWS What's New: Amazon GuardDuty AI-powered investigations accelerate threat response&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-investigation.html" rel="noopener noreferrer"&gt;Amazon GuardDuty User Guide: GuardDuty Investigation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/guardduty/" rel="noopener noreferrer"&gt;Amazon GuardDuty product page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://iamtrail.com/guardduty" rel="noopener noreferrer"&gt;IAMTrail GuardDuty announcements archive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.secureresearch.com/tech-articles/2026-06-23-amazon-guardduty-ai-powered-investigations-acceler-9fab34a357f5.html" rel="noopener noreferrer"&gt;SecureResearch summary of the AWS announcement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>cloud</category>
      <category>ai</category>
    </item>
    <item>
      <title>AWS Lambda MicroVMs: serverless sandboxes for AI and untrusted code</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Sat, 27 Jun 2026 02:02:27 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/aws-lambda-microvms-serverless-sandboxes-for-ai-and-untrusted-code-5dfc</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/aws-lambda-microvms-serverless-sandboxes-for-ai-and-untrusted-code-5dfc</guid>
      <description>&lt;h1&gt;
  
  
  AWS Lambda MicroVMs: serverless sandboxes for AI and untrusted code
&lt;/h1&gt;

&lt;p&gt;AWS just shipped one of the more interesting Lambda launches in years: &lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/aws-lambda-microvms/" rel="noopener noreferrer"&gt;AWS Lambda MicroVMs&lt;/a&gt;. It is not “Lambda functions, but bigger.” It is a new serverless compute primitive aimed at a problem that has become very real with AI agents: how do you safely run code that your application did not write?&lt;/p&gt;

&lt;p&gt;If you are building an AI coding assistant, a browser-based IDE, a data notebook platform, a vulnerability scanner, a multi-tenant CI runner, or any product that executes user-supplied scripts, you usually have to pick two out of three: strong isolation, fast startup, and stateful sessions. Traditional VMs give you isolation but can be slow and operationally heavy. Containers are fast, but shared-kernel isolation is a risk when the workload is untrusted. Functions are great for request-response workloads, but they are not designed for long-lived interactive environments that need to preserve state across user actions.&lt;/p&gt;

&lt;p&gt;Lambda MicroVMs is AWS trying to close that gap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhekhrqgn8eisf777s33a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhekhrqgn8eisf777s33a.png" alt="AWS console view for creating a Lambda MicroVM image" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/aws-lambda-microvms/" rel="noopener noreferrer"&gt;AWS announcement&lt;/a&gt;, Lambda MicroVMs provides VM-level isolation, near-instant launch and resume, and state preservation for user-generated or AI-generated code. The service is built on Firecracker, the same lightweight virtualization technology behind AWS Lambda functions. AWS says Firecracker powers more than 15 trillion monthly Lambda function invocations, which matters because this is not an experimental isolation model bolted onto Lambda; it is based on a virtualization layer AWS already runs at massive scale.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aws.amazon.com/blogs/aws/run-isolated-sandboxes-with-full-lifecycle-control-aws-lambda-introduces-microvms/" rel="noopener noreferrer"&gt;AWS News Blog launch post&lt;/a&gt; frames the service around a new class of multi-tenant applications: AI coding assistants, interactive coding environments, analytics platforms, vulnerability scanners, and game servers that run user-supplied scripts. These systems need one isolated environment per user, job, or session. Lambda MicroVMs gives each session a dedicated MicroVM with no shared kernel and no shared resources between sessions.&lt;/p&gt;

&lt;p&gt;That last point is the key architectural difference. This is not just a container with stricter defaults. The isolation boundary is a virtual machine boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the model works
&lt;/h2&gt;

&lt;p&gt;The developer flow is different from regular Lambda functions. The &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-microvms-guide.html" rel="noopener noreferrer"&gt;Lambda MicroVMs developer guide&lt;/a&gt; describes the lifecycle like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Package your application code and a &lt;code&gt;Dockerfile&lt;/code&gt; into a zip file and upload it to S3.&lt;/li&gt;
&lt;li&gt;Call the Lambda API to create a MicroVM image.&lt;/li&gt;
&lt;li&gt;Lambda builds the image, starts the application, and captures a snapshot of the initialized environment.&lt;/li&gt;
&lt;li&gt;When your app needs a sandbox, call &lt;code&gt;run-microvm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Lambda launches a MicroVM from the snapshot and creates a dedicated HTTPS endpoint.&lt;/li&gt;
&lt;li&gt;When idle, the MicroVM can suspend while preserving memory and disk state.&lt;/li&gt;
&lt;li&gt;When traffic returns, it resumes.&lt;/li&gt;
&lt;li&gt;When the session ends, you terminate it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That snapshot-based startup is what makes the service interesting. Instead of booting from scratch every time, a new MicroVM starts from a pre-initialized image. For interactive workloads, that means the environment can feel ready quickly while still keeping an isolation model closer to VMs than containers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzdnf5uhc7f0488nv8wsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzdnf5uhc7f0488nv8wsg.png" alt="Configuration for running a Lambda MicroVM from an image" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A concrete CLI example
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/microvms-launching.html" rel="noopener noreferrer"&gt;running MicroVMs documentation&lt;/a&gt; shows a &lt;code&gt;run-microvm&lt;/code&gt; command like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda-microvms run-microvm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image-identifier&lt;/span&gt; arn:aws:lambda:us-east-1:123456789012:microvm-image:my-microvm-image &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ingress-network-connectors&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:aws:network-connector:aws-network-connector:ALL_INGRESS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--egress-network-connectors&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:aws:network-connector:aws-network-connector:INTERNET_EGRESS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--idle-policy&lt;/span&gt; &lt;span class="s1"&gt;'{"autoResumeEnabled":true,"maxIdleDurationSeconds":900,"suspendedDurationSeconds":1800}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--maximum-duration-in-seconds&lt;/span&gt; 14400
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only required parameter is the image identifier. The rest control networking, execution role, idle policy, logging, runtime payload, and maximum duration. The maximum time a MicroVM can remain running or suspended is 28,800 seconds, or 8 hours.&lt;/p&gt;

&lt;p&gt;There is also an important networking detail: each MicroVM has its own dedicated endpoint. There is no load balancing across many MicroVMs behind a single endpoint. The endpoint maps to one MicroVM, which fits the “one sandbox per user/session/job” model.&lt;/p&gt;

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

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

&lt;p&gt;AI agents changed the risk profile of application infrastructure. It is now normal to have software generating code, executing shell commands, installing packages, reading files, transforming data, or running tests. If you let that happen inside a generic shared container pool, you inherit a security problem.&lt;/p&gt;

&lt;p&gt;Lambda MicroVMs is useful because it gives product teams a managed primitive for isolated execution without asking them to become virtualization experts. A SaaS company building an AI data analyst could create one MicroVM per user session, preload dependencies, expose a notebook-like endpoint, suspend it after 15 minutes of inactivity, and resume it when the user returns. A security product could run each scan in a clean VM-level boundary. A CI platform could isolate tenant jobs without maintaining its own fleet of Firecracker hosts.&lt;/p&gt;

&lt;p&gt;This does not remove application-level security work. You still need IAM boundaries, careful network egress rules, secret handling, logging, quota controls, and abuse protection. But it moves the hardest part of the compute isolation problem into a managed AWS service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits and tradeoffs to watch
&lt;/h2&gt;

&lt;p&gt;The launch is promising, but it is not a drop-in replacement for every compute pattern.&lt;/p&gt;

&lt;p&gt;First, the service is region-limited at launch. AWS lists availability in US East (N. Virginia), US East (Ohio), US West (Oregon), Asia Pacific (Tokyo), and Europe (Ireland) in the &lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/aws-lambda-microvms/" rel="noopener noreferrer"&gt;announcement&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Second, the lifecycle is session-oriented. If you need a continuously running service, ECS, EKS, EC2, or Lambda Managed Instances may still be a better fit. Lambda MicroVMs shines when you need isolated, stateful, per-user or per-job environments.&lt;/p&gt;

&lt;p&gt;Third, pricing requires a different mental model from Lambda functions. The &lt;a href="https://aws.amazon.com/lambda/pricing/" rel="noopener noreferrer"&gt;Lambda pricing page&lt;/a&gt; says Lambda MicroVMs are priced by compute resources used, snapshot read/write operations, snapshot storage, and standard data transfer. The announcement also notes that you pay for baseline compute resources while the MicroVM is running, and only for active duration of additional resources when the workload exceeds that baseline. In other words: idle suspension is not a minor feature; it is central to making the economics work.&lt;/p&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;This launch shows where serverless is heading. The original Lambda abstraction was “run this function when an event arrives.” Lambda MicroVMs expands the idea to “give me a secure, stateful, short-lived compute environment for this user or agent.” That is a very different primitive.&lt;/p&gt;

&lt;p&gt;For AI-native applications, this is likely to become one of the more important AWS building blocks to evaluate. The winners will be teams that treat Lambda MicroVMs as a sandbox lifecycle service, not as a generic container platform. Model your sessions clearly, minimize what goes into the image, make idle policy explicit, constrain networking, and terminate aggressively when work is done.&lt;/p&gt;

&lt;p&gt;The direction is clear: AWS is turning the infrastructure needed for AI agents into managed primitives. Bedrock gives you models and agent tooling. Lambda MicroVMs gives you safer places to execute the messy code those agents produce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/aws-lambda-microvms/" rel="noopener noreferrer"&gt;AWS introduces Lambda MicroVMs for isolated execution of user and AI-generated code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/aws/run-isolated-sandboxes-with-full-lifecycle-control-aws-lambda-introduces-microvms/" rel="noopener noreferrer"&gt;Run isolated sandboxes with full lifecycle control: AWS Lambda introduces MicroVMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-microvms-guide.html" rel="noopener noreferrer"&gt;AWS Lambda MicroVMs developer guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/microvms-launching.html" rel="noopener noreferrer"&gt;Running and using MicroVMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/lambda/pricing/" rel="noopener noreferrer"&gt;AWS Lambda pricing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
      <category>security</category>
    </item>
    <item>
      <title>AWS Step Functions: 1M ejecuciones/segundo y novedades de la semana</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Mon, 06 Apr 2026 18:51:09 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/aws-step-functions-1m-ejecucionessegundo-y-novedades-de-la-semana-105o</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/aws-step-functions-1m-ejecucionessegundo-y-novedades-de-la-semana-105o</guid>
      <description>&lt;h1&gt;
  
  
  AWS Step Functions Express Workflows ya soporta hasta 1 millón de ejecuciones por segundo
&lt;/h1&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%2Fd1.awsstatic.com%2Flogos%2Faws-logo-lockups%2Fpoweredbyaws%2FPB_AWS_logo_RGB_stacked.547f032d90171f5c4f3c0e2eaa9f0b0d7c5fd2d.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%2Fd1.awsstatic.com%2Flogos%2Faws-logo-lockups%2Fpoweredbyaws%2FPB_AWS_logo_RGB_stacked.547f032d90171f5c4f3c0e2eaa9f0b0d7c5fd2d.png" alt="AWS Architecture" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esta semana AWS duplicó el límite de ejecuciones concurrentes en Step Functions Express Workflows, RDS Proxy para PostgreSQL mejoró su manejo de conexiones, y Lambda Powertools for Python v3 agregó métricas custom más granulares.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Noticias principales
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. AWS Step Functions Express Workflows — 1M ejecuciones/segundo
&lt;/h3&gt;

&lt;p&gt;AWS duplicó el límite de ejecuciones concurrentes de 500K a 1 millón por segundo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Por qué importa:&lt;/strong&gt; Si tenés workloads de procesamiento en tiempo real (IoT, stream processing, APIs de alta frecuencia), ahora podés escalar el doble sin rearchitecturar.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Amazon RDS Proxy for PostgreSQL — 10K conexiones simultáneas
&lt;/h3&gt;

&lt;p&gt;Mejoró el pooling de conexiones para manejar picos de tráfico.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Por qué importa:&lt;/strong&gt; Aplicaciones con muchos microservicios o serverless functions que acceden a PostgreSQL ya no necesitan implementar connection pooling manual.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. AWS Lambda Powertools for Python v3 — Métricas custom
&lt;/h3&gt;

&lt;p&gt;Ahora podés emitir métricas custom con dimensions específicas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Por qué importa:&lt;/strong&gt; Monitoring más granular sin escribir código boilerplate.&lt;/p&gt;

&lt;h2&gt;
  
  
  📋 Otras noticias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AWS Config Rules ahora soporta EKS&lt;/li&gt;
&lt;li&gt;Amazon S3 Intelligent-Tiering agregó Archive Instant Access tier&lt;/li&gt;
&lt;li&gt;AWS Backup agregó soporte para Amazon MemoryDB&lt;/li&gt;
&lt;li&gt;Amazon EC2 M7i-flex instances ya disponibles en más regiones&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📅 Eventos en Español
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Community Day Argentina 2026&lt;/strong&gt; — 15 de abril, Buenos Aires&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EKS Workshop Latinoamérica&lt;/strong&gt; — 22 de abril, virtual&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📚 Artículos interesantes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cómo debuguear Lambda functions con X-Ray y Powertools&lt;/strong&gt; — Tutorial paso a paso&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecting multi-tenant SaaS on AWS&lt;/strong&gt; — Patrones de isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost optimization for EKS clusters&lt;/strong&gt; — Spot instances + HPA&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Fuentes: AWS What\u0027s New, AWS Blog, Last Week in AWS, InfoQ, Desplegando.cloud&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Artículo prueba con variable de entorno DEVTO_API_KEY</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Mon, 06 Apr 2026 01:21:25 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/articulo-prueba-con-variable-de-entorno-devtoapikey-a37</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/articulo-prueba-con-variable-de-entorno-devtoapikey-a37</guid>
      <description>&lt;h1&gt;
  
  
  ¡Funciona! Variable de entorno configurada
&lt;/h1&gt;

&lt;p&gt;Este artículo demuestra que la variable de entorno DEVTO_API_KEY está correctamente configurada en el pod de OpenClaw.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuración exitosa
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes secret creado&lt;/li&gt;
&lt;li&gt;Variable inyectada en el pod&lt;/li&gt;
&lt;li&gt;API key segura fuera del workspace&lt;/li&gt;
&lt;li&gt;Autenticación funcionando&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; kubernetes, security, devto, aws&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Creado automáticamente por el agente de CloudAcademy.ar&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>security</category>
      <category>devto</category>
      <category>aws</category>
    </item>
    <item>
      <title>Artículo de prueba - Conexión dev.to API</title>
      <dc:creator>Matias Martinez</dc:creator>
      <pubDate>Mon, 06 Apr 2026 01:05:54 +0000</pubDate>
      <link>https://dev.to/matias_martinez_185d9e0ee/articulo-de-prueba-conexion-devto-api-234b</link>
      <guid>https://dev.to/matias_martinez_185d9e0ee/articulo-de-prueba-conexion-devto-api-234b</guid>
      <description>&lt;h1&gt;
  
  
  Artículo de prueba
&lt;/h1&gt;

&lt;p&gt;Este es un artículo de prueba para verificar la conexión con la API de dev.to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contenido de prueba
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Verificación de autenticación&lt;/li&gt;
&lt;li&gt;Creación de artículos&lt;/li&gt;
&lt;li&gt;Configuración del blog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; testing, api, aws&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Creado automáticamente por el agente de CloudAcademy.ar&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>api</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
