<?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: Sibonelo N.</title>
    <description>The latest articles on DEV Community by Sibonelo N. (@neloh).</description>
    <link>https://dev.to/neloh</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%2F758002%2F96440ec4-036d-4c61-8eeb-465b82ccbc99.jpeg</url>
      <title>DEV Community: Sibonelo N.</title>
      <link>https://dev.to/neloh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/neloh"/>
    <language>en</language>
    <item>
      <title>What Is AgentCore Runtime, Really? Breaking Down the Thing I Already Benchmarked</title>
      <dc:creator>Sibonelo N.</dc:creator>
      <pubDate>Sun, 16 Aug 2026 10:41:46 +0000</pubDate>
      <link>https://dev.to/neloh/what-is-agentcore-runtime-really-breaking-down-the-thing-i-already-benchmarked-5bbd</link>
      <guid>https://dev.to/neloh/what-is-agentcore-runtime-really-breaking-down-the-thing-i-already-benchmarked-5bbd</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/neloh/bedrock-agentcore-runtime-latency-what-actually-matters-multi-language-benchmarking-3dko"&gt;first article&lt;/a&gt; I measured AgentCore Runtime six different ways: four languages, three frameworks, PUBLIC vs VPC-mode, in-VPC vs external callers. Lots of numbers. What I skipped over is the more basic question: what is Runtime actually &lt;em&gt;doing&lt;/em&gt; to produce those numbers?&lt;/p&gt;

&lt;p&gt;This article fills that gap, using the same &lt;a href="https://github.com/Neloh/agentcore-latency-benchmarks" rel="noopener noreferrer"&gt;benchmark repo&lt;/a&gt; as the worked example instead of starting from a blank slate. It also covers something the first article couldn't have: two days after that benchmark ran, AWS shipped a second compute type for Runtime entirely. More on that below.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AgentCore Runtime Is
&lt;/h2&gt;

&lt;p&gt;AWS describes it plainly: Runtime is "a secure, serverless runtime environment purpose-built for deploying and scaling dynamic AI agents and tools," offering fast cold starts, session isolation, built-in identity, and support for multi-modal, multi-agent workloads. It doesn't care which framework you brought (CrewAI, LangGraph, LlamaIndex, Google ADK, OpenAI Agents SDK, Strands, or nothing at all) or which model you call (Bedrock, OpenAI, Gemini, anything). It speaks two agent-to-agent/tool protocols out of the box: MCP and A2A.&lt;/p&gt;

&lt;p&gt;That framework-agnostic, model-agnostic design is exactly why Finding 1 and Finding 5 in the benchmark article landed the way they did — container language and framework choice added zero measurable overhead, because Runtime doesn't touch either. It just runs your container and enforces a contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Actually Inside a microVM
&lt;/h2&gt;

&lt;p&gt;I used the word "microVM" in the first article without stopping to explain it, so here it is properly: a microVM is a minimal virtual machine, built on the open-source &lt;a href="https://firecracker-microvm.github.io/" rel="noopener noreferrer"&gt;Firecracker&lt;/a&gt; virtualization technology that also powers AWS Lambda. It gives you real VM-level isolation — its own kernel, its own memory space, no shared host kernel with any other tenant — but strips away everything a general-purpose VM boots that an agent session doesn't need, so it can start in tens of milliseconds instead of the seconds a traditional EC2 instance takes.&lt;/p&gt;

&lt;p&gt;That's the specific trade AgentCore Runtime is making by default: stronger isolation than a container (which shares the host kernel), at close to container-speed startup, rather than the isolation of a full EC2 instance at EC2 boot times. Every session gets one, and it's why the isolation guarantee reads the way it does in the docs: "no shared state, no shared filesystem" between sessions, even concurrent ones for the same runtime.&lt;/p&gt;

&lt;p&gt;Here's what that actually looks like on a warm call — the case that produced the 80-160ms in-VPC numbers from article 1:&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%2Fpws39udct8cdlj3bthri.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%2Fpws39udct8cdlj3bthri.png" alt="Warm invocation sequence" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here's the cold path — a brand-new &lt;code&gt;sessionId&lt;/code&gt; with no existing microVM to route to:&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%2Fpjh20zvi62lmzd94keqe.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%2Fpjh20zvi62lmzd94keqe.png" alt="Cold start sequence" width="799" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only structural difference between the two is one extra step: provisioning a microVM and waiting for &lt;code&gt;/ping&lt;/code&gt; to report &lt;code&gt;Healthy&lt;/code&gt; before the first &lt;code&gt;/invocations&lt;/code&gt; call can go through. Everything downstream of that is identical. That single step is also the entire explanation for why cold start is seconds and warm is milliseconds — it's not a slower code path, it's a whole extra phase that warm calls skip.&lt;/p&gt;

&lt;p&gt;Here's a warm call for real, run through the console's own test panel against one of the benchmark repo's echo runtimes:&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%2Fk8vzzwztlbyvghkwx24k.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%2Fk8vzzwztlbyvghkwx24k.png" alt="Console test/invoke panel showing a live warm invocation" width="799" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;request_processed_ms: 37&lt;/code&gt;. That's not from a load-testing script, it's a single live click. The rest of the response — &lt;code&gt;container_id&lt;/code&gt;, &lt;code&gt;uptime_seconds&lt;/code&gt;, &lt;code&gt;language&lt;/code&gt; — comes straight from the runtime's own code, which is worth looking at directly next.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Building Blocks
&lt;/h2&gt;

&lt;p&gt;Peel back "Runtime" and there are four concrete objects, each with its own lifecycle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runtime&lt;/strong&gt; — the top-level resource. Has a unique identity and is versioned. This is the thing you &lt;code&gt;CreateAgentRuntime&lt;/code&gt; once and then update repeatedly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version&lt;/strong&gt; — an immutable snapshot. Every time you change the container image, protocol settings, or network settings, a new version is cut. Version 1 is created automatically the first time you create the Runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Endpoint&lt;/strong&gt; — an addressable ARN pointing at a specific version. A &lt;code&gt;DEFAULT&lt;/code&gt; endpoint is created automatically and always tracks the latest version; you can also create named endpoints (dev/test/prod) that pin to a specific version deliberately, so you're not forced onto whatever was last deployed. Endpoints move through &lt;code&gt;CREATING → READY&lt;/code&gt; (or &lt;code&gt;CREATE_FAILED&lt;/code&gt;), and &lt;code&gt;UPDATING → READY&lt;/code&gt; (or &lt;code&gt;UPDATE_FAILED&lt;/code&gt;) without downtime to callers.&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%2F58ekeaym7h38ku3e8wg3.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%2F58ekeaym7h38ku3e8wg3.png" alt="Runtime, Version, and Endpoint relationship" width="715" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the theory. Here's what it looks like on an actual runtime — &lt;code&gt;goHttpLatencyTest&lt;/code&gt;, compute type &lt;code&gt;microVMs&lt;/code&gt;, one version, two endpoints:&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%2F4w1nvt7m0gefx56bp4f0.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%2F4w1nvt7m0gefx56bp4f0.png" alt="Runtime detail page showing compute type, versions, and endpoints" width="799" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And drilling into one of those endpoints:&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%2Foyyfz5kqb1ltjiyr35tm.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%2Foyyfz5kqb1ltjiyr35tm.png" alt="Endpoint detail page" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session&lt;/strong&gt; — the actual unit of execution. Identified by a &lt;code&gt;runtimeSessionId&lt;/code&gt; (yours, or generated for you on first call), a session runs in a dedicated microVM with fully isolated CPU, memory, and filesystem. It persists for up to 8 hours, moves between &lt;code&gt;Active&lt;/code&gt; and &lt;code&gt;Idle&lt;/code&gt;, and gets &lt;code&gt;Terminated&lt;/code&gt; after 15 minutes of inactivity, at the 8-hour cap, or if deemed unhealthy. Termination destroys the entire microVM and sanitizes memory — reusing the same &lt;code&gt;runtimeSessionId&lt;/code&gt; afterward just gets you a fresh environment, not the old one back.&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%2F4qlxoq7tow1r9reo47sp.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%2F4qlxoq7tow1r9reo47sp.png" alt="Session lifecycle state diagram" width="412" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the mechanism behind the repo's session-affinity test: embedding a random container ID at startup and checking whether it stays constant across calls is really just checking "am I still inside the same microVM, or did my session get torn down and rebuilt."&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Protocols, One Contract Each
&lt;/h2&gt;

&lt;p&gt;Whatever's inside the container, Runtime expects one of three fixed contracts, chosen when you create the Runtime:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Main path&lt;/th&gt;
&lt;th&gt;Health check&lt;/th&gt;
&lt;th&gt;Shape&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;8080&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /invocations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET /ping&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;REST, optional SSE/WebSocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;td&gt;8000&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /mcp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET /ping&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON-RPC 2.0, Streamable-HTTP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A2A&lt;/td&gt;
&lt;td&gt;9000&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET /.well-known/agent-card.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON-RPC 2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every echo runtime in the benchmark repo — Go, Node.js, Java, Python — implements exactly the HTTP contract: bind &lt;code&gt;0.0.0.0&lt;/code&gt;, answer &lt;code&gt;/ping&lt;/code&gt; with a health status, answer &lt;code&gt;/invocations&lt;/code&gt; with JSON. Nothing about the contract is language-specific, which is the whole reason a 22 MB Go binary and a 494 MB Java/Corretto image land within 10ms of each other once warm: they're both just satisfying the same thin HTTP contract, and the platform's own routing floor dwarfs whatever the container itself does with the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Looks Like in Code
&lt;/h2&gt;

&lt;p&gt;It's worth seeing how little code actually satisfies that contract. Here's the Go runtime's entire structure — no subdirectories, no dependencies, one source file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source/agentcore-go-runtime/
├── Dockerfile
├── deploy.sh
├── go.mod
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Dockerfile is a standard two-stage build: compile a static binary, then copy just the binary into a bare &lt;code&gt;alpine&lt;/code&gt; image. Nothing else goes in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Multi-stage build for minimal container size&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.22-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy module file (no external deps)&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod ./&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; main.go .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm64 go build &lt;span class="nt"&gt;-ldflags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-s -w"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /runtime main.go

&lt;span class="c"&gt;# Final image: minimal alpine&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:3.20&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk &lt;span class="nt"&gt;--no-cache&lt;/span&gt; add ca-certificates
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /runtime /runtime&lt;/span&gt;

&lt;span class="c"&gt;# AgentCore HTTP protocol requires port 8080&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;adduser &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; 1001 agentcore
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; agentcore&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["/runtime"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;GOARCH=arm64&lt;/code&gt; isn't a style choice — AgentCore's Firecracker microVMs are ARM64, so anything built for the wrong architecture fails at deploy time, not at runtime. And &lt;code&gt;main.go&lt;/code&gt; itself is just two HTTP handlers wired to the two paths from the contract table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PingResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;"Healthy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;TimeOfLastUpdate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unix&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;invocations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ...decode the request, run whatever "action" it asked for...&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"_meta"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ContainerID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;containerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;UptimeSeconds&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startupTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Seconds&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;RequestProcessedMs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;requestProcessedMs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Language&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="s"&gt;"go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/ping"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/invocations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;invocations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those exact field names — &lt;code&gt;container_id&lt;/code&gt;, &lt;code&gt;uptime_seconds&lt;/code&gt;, &lt;code&gt;request_processed_ms&lt;/code&gt;, &lt;code&gt;language&lt;/code&gt; — are what showed up in the test-panel response a few sections back. There's no gap between the code and the observed behavior; the console screenshot is this &lt;code&gt;main.go&lt;/code&gt; running.&lt;/p&gt;

&lt;p&gt;The console will even generate a starter invocation snippet for any runtime you create, in Python, TypeScript, or JavaScript:&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%2F6zryxqylag04msrfwhws.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%2F6zryxqylag04msrfwhws.png" alt="Console-generated invocation code sample" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why PUBLIC vs VPC-Mode Didn't Move the Numbers
&lt;/h2&gt;

&lt;p&gt;Network mode changes &lt;em&gt;where the container's network interface lives&lt;/em&gt; — platform-managed infrastructure for PUBLIC, an ENI in your own subnet for VPC-mode — not how sessions, versions, or the request path work. Once a session's microVM is warm, the request still goes through the same routing and lands in the same kind of isolated execution environment either way. That's why Finding 3 showed identical warm latency between the two: the difference is cold-start ENI attachment time, not steady-state architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Alternative: Runtime Instances and Capacity Providers
&lt;/h2&gt;

&lt;p&gt;Everything above describes the microVM compute type — the only one that existed when I ran the first article's benchmarks. On 06 Aug 2026, two days after that article published, AWS announced a second compute type for Runtime: &lt;strong&gt;Instances&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg0dp1w7ritj6d3c0xqz6.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%2Fg0dp1w7ritj6d3c0xqz6.png" alt="AgentCore console showing the new Instances banner and Capacity providers tab" width="799" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Where microVMs are fully AWS-managed, ephemeral, and capped at 8 hours per session, Instances runs your agent on Amazon EC2 managed instances &lt;em&gt;inside your own AWS account&lt;/em&gt;. AgentCore still provisions, patches, scales, and tears them down for you — you don't do standard EC2 lifecycle operations on them yourself — but the compute lives in your account, so your existing Savings Plans, Reserved Instances, and On-Demand Capacity Reservations apply, and the instances (and any attached EBS volumes) show up in your own EC2 console.&lt;/p&gt;

&lt;p&gt;The infrastructure itself is defined by a new resource called a &lt;strong&gt;capacity provider&lt;/strong&gt;: a reusable template specifying the OS, allowed instance types, VPC/subnets, storage volumes, and IAM roles. You attach a capacity provider to a Runtime at creation time via &lt;code&gt;capacityProviderConfiguration&lt;/code&gt;, and you can't change compute type after that — it's a decision made once, per Runtime.&lt;/p&gt;

&lt;p&gt;What Instances buys you that microVMs structurally can't:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Characteristic&lt;/th&gt;
&lt;th&gt;microVMs&lt;/th&gt;
&lt;th&gt;Instances&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Best suited for&lt;/td&gt;
&lt;td&gt;Lightweight, fast-scaling API agents&lt;/td&gt;
&lt;td&gt;Long-running, stateful, or collaborative workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum session duration&lt;/td&gt;
&lt;td&gt;Up to 8 hours&lt;/td&gt;
&lt;td&gt;Up to 14 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operating systems&lt;/td&gt;
&lt;td&gt;Linux containers (arm64 only)&lt;/td&gt;
&lt;td&gt;Linux (x86_64 and arm64)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Networking&lt;/td&gt;
&lt;td&gt;PUBLIC or VPC&lt;/td&gt;
&lt;td&gt;VPC only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents per session&lt;/td&gt;
&lt;td&gt;One runtime hosts one agent (1:1)&lt;/td&gt;
&lt;td&gt;One session can host multiple agents (1:N)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU access&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;Supported (g4dn/g5/g6/g6e/gr6/g6f/gr6f/g7e, inf2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing&lt;/td&gt;
&lt;td&gt;Consumption-based, billed by AgentCore&lt;/td&gt;
&lt;td&gt;Runs in your account; your EC2 pricing agreements apply&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two consequences worth calling out for anyone coming from the first article's mental model:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sessions can now survive stop/resume, not just stay idle.&lt;/strong&gt; On microVMs, termination is final — a reused &lt;code&gt;runtimeSessionId&lt;/code&gt; after termination gets a brand-new environment. On Instances, when a session hits its lifetime or is stopped, AgentCore tears down the EC2 instance but &lt;em&gt;keeps the attached EBS volume&lt;/em&gt;. Invoking the same &lt;code&gt;runtimeSessionId&lt;/code&gt; again provisions a fresh instance, re-attaches that volume, and your agent's filesystem picks up where it left off — potentially on a freshly patched machine image.&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%2Fbikh552wowbglrxc6qc7.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%2Fbikh552wowbglrxc6qc7.png" alt="Instances stop/resume sequence with persistent EBS volume" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple agents can now share one execution environment.&lt;/strong&gt; The microVM model is strictly 1:1 — one Runtime, one agent, one microVM per session. On Instances, if two separate Runtimes are attached to the &lt;em&gt;same&lt;/em&gt; capacity provider and invoked with the &lt;em&gt;same&lt;/em&gt; &lt;code&gt;runtimeSessionId&lt;/code&gt;, both agents land on the same EC2 instance and share its filesystem. That's a materially different collaboration primitive than anything the microVM model offers.&lt;/p&gt;

&lt;p&gt;None of the numbers in the first article measured Instances — that compute type didn't exist yet, and every benchmark there was run against microVMs specifically. That's a legitimate follow-up benchmark on its own: does a GPU-backed Instances session behave the same way under the "does language matter" and "does network mode matter" questions, or does the EC2-backed model change the shape of the answer? Worth its own repo, not a retrofit onto this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seeing It for Real
&lt;/h2&gt;

&lt;p&gt;Everything above is easier to believe with an actual &lt;code&gt;DescribeAgentRuntime&lt;/code&gt; response in front of you instead of a docs paraphrase. Here's the real output for one of the benchmark repo's own runtimes, the Go echo container in PUBLIC mode:&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;"agentRuntimeArn"&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:bedrock-agentcore:us-east-1:&amp;lt;account-id&amp;gt;:runtime/goHttpLatencyTest-5CKthu5tD0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentRuntimeName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"goHttpLatencyTest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentRuntimeVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"networkConfiguration"&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;"networkMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PUBLIC"&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;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"READY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lifecycleConfiguration"&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;"idleRuntimeSessionTimeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"maxLifetime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28800&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;"agentRuntimeArtifact"&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;"containerConfiguration"&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;"containerUri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;account-id&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/agentcore-go-runtime:http-v1"&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;"protocolConfiguration"&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;"serverProtocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HTTP"&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;Two numbers to notice: &lt;code&gt;idleRuntimeSessionTimeout: 900&lt;/code&gt; and &lt;code&gt;maxLifetime: 28800&lt;/code&gt; are exactly the 15-minute idle timeout and 8-hour max lifetime from the session lifecycle diagram above, in seconds. That's not a coincidence or a rounded approximation — it's the literal same value the docs describe, straight from the API.&lt;/p&gt;

&lt;p&gt;For the VPC-mode Python runtime, the only structural difference is the &lt;code&gt;networkConfiguration&lt;/code&gt; block growing to include &lt;code&gt;securityGroups&lt;/code&gt; and &lt;code&gt;subnets&lt;/code&gt; — everything else (protocol, lifecycle, artifact shape) is identical. That's the API-level version of Finding 3: PUBLIC and VPC-mode differ in exactly one config block and nowhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html" rel="noopener noreferrer"&gt;Amazon Bedrock AgentCore overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-how-it-works.html" rel="noopener noreferrer"&gt;AgentCore Runtime: microVMs, versions, endpoints, sessions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-instances-how-it-works.html" rel="noopener noreferrer"&gt;AgentCore Runtime: Instances and capacity providers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/blogs/aws/runtime-instances-persistent-compute-for-production-ai-agents-on-amazon-bedrock-agentcore/" rel="noopener noreferrer"&gt;AWS News Blog: Runtime instances — persistent compute for production AI agents&lt;/a&gt; (06 Aug 2026)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://firecracker-microvm.github.io/" rel="noopener noreferrer"&gt;Firecracker microVM project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Neloh/agentcore-latency-benchmarks" rel="noopener noreferrer"&gt;Benchmark repo: agentcore-latency-benchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Neloh/agentcore-latency-benchmarks/tree/main/source/agentcore-go-runtime" rel="noopener noreferrer"&gt;Go runtime source: main.go, Dockerfile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/neloh/bedrock-agentcore-runtime-latency-what-actually-matters-multi-language-benchmarking-3dko"&gt;Article 1: Bedrock AgentCore Runtime Latency&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>bedrock</category>
      <category>serverless</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Bedrock AgentCore Runtime Latency: What Actually Matters (Multi-Language Benchmarking)</title>
      <dc:creator>Sibonelo N.</dc:creator>
      <pubDate>Tue, 04 Aug 2026 20:24:28 +0000</pubDate>
      <link>https://dev.to/neloh/bedrock-agentcore-runtime-latency-what-actually-matters-multi-language-benchmarking-3dko</link>
      <guid>https://dev.to/neloh/bedrock-agentcore-runtime-latency-what-actually-matters-multi-language-benchmarking-3dko</guid>
      <description>&lt;p&gt;This article presents comprehensive latency benchmarking results for AWS Bedrock AgentCore Runtime across four programming languages (Go, Node.js, Java, Python), three framework options (raw boto3, Strands SDK, LangChain), multiple network configurations, and caller locations. The goal is to provide data-driven guidance on what design choices affect latency and what does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;AgentCore Runtime is the compute layer for hosting agents and tools in Bedrock AgentCore. Customers frequently ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which language should I write my runtime container in?&lt;/li&gt;
&lt;li&gt;Does PUBLIC vs VPC network mode affect performance?&lt;/li&gt;
&lt;li&gt;Should I use Strands SDK, LangChain, or raw SDK calls?&lt;/li&gt;
&lt;li&gt;Does the client SDK language matter?&lt;/li&gt;
&lt;li&gt;Where should my caller run for best latency?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article answers each question with measured data from a controlled test environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Region: us-east-1&lt;/li&gt;
&lt;li&gt;Protocol: HTTP (port 8080)&lt;/li&gt;
&lt;li&gt;Model (for real agent tests): Claude Haiku 4.5 via cross-region inference profile&lt;/li&gt;
&lt;li&gt;VPC: Private subnets with &lt;code&gt;com.amazonaws.us-east-1.bedrock-agentcore&lt;/code&gt; interface endpoint&lt;/li&gt;
&lt;li&gt;Caller locations tested: In-VPC Lambda (private subnet) and external (boto3 with connection reuse)&lt;/li&gt;
&lt;li&gt;All container images built for linux/arm64 (AgentCore Firecracker VMs are ARM64)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finding 1: Container language does not affect warm latency
&lt;/h2&gt;

&lt;p&gt;Four echo runtimes were deployed, each implementing the same trivial HTTP server (receive JSON, return it with metadata). All use the HTTP protocol on port 8080.&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%2Fm1ip0og8rqapo12qsq27.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%2Fm1ip0og8rqapo12qsq27.png" alt="4-Language Latency Comparison" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Image Size&lt;/th&gt;
&lt;th&gt;In-VPC Median&lt;/th&gt;
&lt;th&gt;External Mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;22 MB&lt;/td&gt;
&lt;td&gt;85ms&lt;/td&gt;
&lt;td&gt;968ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;229 MB&lt;/td&gt;
&lt;td&gt;80ms&lt;/td&gt;
&lt;td&gt;950ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java (Corretto 21)&lt;/td&gt;
&lt;td&gt;494 MB&lt;/td&gt;
&lt;td&gt;77ms&lt;/td&gt;
&lt;td&gt;945ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python (3.12 + gunicorn)&lt;/td&gt;
&lt;td&gt;52 MB&lt;/td&gt;
&lt;td&gt;84ms&lt;/td&gt;
&lt;td&gt;937ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All four are within 10ms of each other on warm in-VPC calls. The platform routing floor dominates. Language choice should be driven by team expertise and ecosystem, not latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 2: Caller location is the single biggest factor
&lt;/h2&gt;

&lt;p&gt;The same runtime invoked from three different locations:&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%2Fkwe68ayg45o87vp6n08z.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%2Fkwe68ayg45o87vp6n08z.png" alt="VPC vs External" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Caller Location&lt;/th&gt;
&lt;th&gt;Mean Latency&lt;/th&gt;
&lt;th&gt;What Adds Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;In-VPC Lambda (VPC endpoint)&lt;/td&gt;
&lt;td&gt;80-90ms&lt;/td&gt;
&lt;td&gt;Platform routing only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External (boto3, connection reuse)&lt;/td&gt;
&lt;td&gt;937-968ms&lt;/td&gt;
&lt;td&gt;Network RTT to region&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External (AWS CLI, no reuse)&lt;/td&gt;
&lt;td&gt;1,750-1,830ms&lt;/td&gt;
&lt;td&gt;Network RTT + TLS + SDK init&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Placing callers in the same VPC with a &lt;code&gt;bedrock-agentcore&lt;/code&gt; interface endpoint provides 5-10x latency improvement. This is the single most impactful optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 3: PUBLIC vs VPC-MODE runtime has no latency impact
&lt;/h2&gt;

&lt;p&gt;VPC-MODE places the container's ENI in your private subnet. PUBLIC mode runs on platform-managed infrastructure.&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%2F1ii21elgnougpwrmeasw.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%2F1ii21elgnougpwrmeasw.png" alt="PUBLIC vs VPC-MODE" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;PUBLIC Median&lt;/th&gt;
&lt;th&gt;VPC-MODE Median&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;87ms&lt;/td&gt;
&lt;td&gt;85ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;80ms&lt;/td&gt;
&lt;td&gt;84ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;77ms&lt;/td&gt;
&lt;td&gt;85ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;84ms&lt;/td&gt;
&lt;td&gt;87ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Identical once warm. VPC-MODE has higher cold-start spikes (ENI attachment takes 500-2500ms on first invocation) and takes longer to provision (~2.5 minutes vs 5 seconds for PUBLIC). Use VPC-MODE for security and compliance (network isolation, access to private resources), not for performance.&lt;/p&gt;

&lt;p&gt;The 3-way comparison (External vs In-VPC PUBLIC vs In-VPC VPC-MODE) shows the full picture:&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%2F4zfr4r9n5exvwuuugsf5.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%2F4zfr4r9n5exvwuuugsf5.png" alt="3-Way Comparison" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 4: Client SDK language does not affect warm latency
&lt;/h2&gt;

&lt;p&gt;Three Lambda functions were deployed, each written in its native language, calling its corresponding VPC-mode runtime:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lambda Language&lt;/th&gt;
&lt;th&gt;SDK&lt;/th&gt;
&lt;th&gt;Warm Median&lt;/th&gt;
&lt;th&gt;Cold Start&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;aws-sdk-go-v2&lt;/td&gt;
&lt;td&gt;98ms&lt;/td&gt;
&lt;td&gt;904ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;@aws-sdk/client-bedrock-agentcore&lt;/td&gt;
&lt;td&gt;115ms&lt;/td&gt;
&lt;td&gt;873ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;boto3&lt;/td&gt;
&lt;td&gt;96ms&lt;/td&gt;
&lt;td&gt;2,631ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Warm latency is identical. Cold start differs: Go and Node.js initialize in under 1 second, Python (boto3) takes 2.6 seconds due to interpreter and credential chain resolution overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 5: Framework choice adds zero measurable overhead
&lt;/h2&gt;

&lt;p&gt;Three variants of the same SageMaker SME agent were deployed, all using Claude Haiku 4.5 with the same system prompt and question:&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%2F0k4r4uwssy3i0whu07oh.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%2F0k4r4uwssy3i0whu07oh.png" alt="Framework Comparison" width="799" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Framework Overhead&lt;/th&gt;
&lt;th&gt;Image Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raw boto3 (invoke_model)&lt;/td&gt;
&lt;td&gt;0.2ms&lt;/td&gt;
&lt;td&gt;180 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strands Agents SDK&lt;/td&gt;
&lt;td&gt;0.2ms&lt;/td&gt;
&lt;td&gt;347 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LangChain (ChatBedrock)&lt;/td&gt;
&lt;td&gt;0.1ms&lt;/td&gt;
&lt;td&gt;438 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Framework processing overhead is under 0.3ms for all three. The model inference call (5-26 seconds depending on output length) accounts for over 95% of end-to-end latency. Choose frameworks based on developer productivity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Raw boto3&lt;/strong&gt;: Lightest image, full control, manual orchestration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strands SDK&lt;/strong&gt;: Built-in tool registration, memory management, conversation handling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LangChain&lt;/strong&gt;: Rich ecosystem of chains, RAG integrations, prompt templates&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finding 6: Connection pool size matters only at high concurrency
&lt;/h2&gt;

&lt;p&gt;Connection pool stress tests with boto3 (urllib3 backend) at varying pool sizes:&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%2Fdmmt70hf84lg9r74c5n3.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%2Fdmmt70hf84lg9r74c5n3.png" alt="Connection Pool Stress" width="799" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concurrency&lt;/th&gt;
&lt;th&gt;Pool=2 Mean&lt;/th&gt;
&lt;th&gt;Pool=10 Mean (default)&lt;/th&gt;
&lt;th&gt;Pool=50 Mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 thread&lt;/td&gt;
&lt;td&gt;84ms&lt;/td&gt;
&lt;td&gt;81ms&lt;/td&gt;
&lt;td&gt;81ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 threads&lt;/td&gt;
&lt;td&gt;153ms&lt;/td&gt;
&lt;td&gt;139ms&lt;/td&gt;
&lt;td&gt;132ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50 threads&lt;/td&gt;
&lt;td&gt;204ms&lt;/td&gt;
&lt;td&gt;155ms&lt;/td&gt;
&lt;td&gt;113ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100 threads&lt;/td&gt;
&lt;td&gt;254ms&lt;/td&gt;
&lt;td&gt;138ms&lt;/td&gt;
&lt;td&gt;142ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No errors at any concurrency level. The default pool size (10) is adequate for most workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 7: Model inference dominates real agent latency
&lt;/h2&gt;

&lt;p&gt;For a real SageMaker SME agent answering technical questions:&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%2F814spdrrpy5oex6cx46i.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%2F814spdrrpy5oex6cx46i.png" alt="Echo vs Real Agent" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Latency&lt;/th&gt;
&lt;th&gt;Percentage of E2E&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Container processing (framework + parsing)&lt;/td&gt;
&lt;td&gt;less than 1ms&lt;/td&gt;
&lt;td&gt;less than 0.01%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Platform routing (SigV4, DDB, Firecracker)&lt;/td&gt;
&lt;td&gt;95-375ms&lt;/td&gt;
&lt;td&gt;3-5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model inference (Claude Haiku 4.5)&lt;/td&gt;
&lt;td&gt;5,700-26,000ms&lt;/td&gt;
&lt;td&gt;95%+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The model call scales with output token count (approximately 5ms per output token for Haiku 4.5).&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually matters (ranked)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rank&lt;/th&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Caller location (in-VPC vs external)&lt;/td&gt;
&lt;td&gt;5-10x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Model choice (for real agents)&lt;/td&gt;
&lt;td&gt;Determines total time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;SDK cold start (Go/Node vs Python)&lt;/td&gt;
&lt;td&gt;3x on first call only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Connection pool size&lt;/td&gt;
&lt;td&gt;Mild at high concurrency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Container language&lt;/td&gt;
&lt;td&gt;Zero impact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Runtime network mode (PUBLIC vs VPC)&lt;/td&gt;
&lt;td&gt;Zero impact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Client SDK language (warm)&lt;/td&gt;
&lt;td&gt;Zero impact&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Optimization Recommendations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Place callers in-VPC&lt;/strong&gt; with a &lt;code&gt;bedrock-agentcore&lt;/code&gt; interface endpoint for 5-10x latency reduction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reuse SDK clients&lt;/strong&gt; across invocations. Never create a new client per call. In Lambda, initialize at module scope outside the handler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do not optimize container language for latency.&lt;/strong&gt; Pick what your team knows. The platform routing floor makes it invisible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use VPC-MODE for security&lt;/strong&gt;, not performance. Identical once warm.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consolidate multi-tool agents&lt;/strong&gt; into fewer runtimes. Each sequential InvokeAgentRuntime call adds platform routing overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use streaming&lt;/strong&gt; for better perceived performance. Model inference is the bottleneck.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Code Configuration Support
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Code Config (zip to S3)&lt;/th&gt;
&lt;th&gt;Container Config (Docker)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Yes (3.10 through 3.14)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;Yes (NODE_22)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Caller (Lambda / ECS / App)
  -&amp;gt; [VPC Endpoint or Public Endpoint]
    -&amp;gt; AgentCore Platform (SigV4 validation, session lookup, routing)
      -&amp;gt; Container (PUBLIC: platform VM | VPC: ENI in your subnet)
        -&amp;gt; [Optional] Bedrock InvokeModel (model inference)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;All source code, raw data, Lambda functions, and charts are available here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Neloh" rel="noopener noreferrer"&gt;
        Neloh
      &lt;/a&gt; / &lt;a href="https://github.com/Neloh/agentcore-latency-benchmarks" rel="noopener noreferrer"&gt;
        agentcore-latency-benchmarks
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AgentCore Runtime latency benchmarking: Go, Node.js, Java, Python across PUBLIC/VPC modes
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AgentCore Runtime Latency Benchmarks&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Comprehensive latency benchmarking of AWS Bedrock AgentCore Runtime across 4 programming languages (Go, Node.js, Java, Python), multiple network configurations, and caller locations.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Key Findings&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Factor&lt;/th&gt;

&lt;th&gt;Impact on Warm Latency&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;
&lt;br&gt;
&lt;strong&gt;Caller location&lt;/strong&gt; (in-VPC vs external)&lt;/td&gt;

&lt;td&gt;
&lt;br&gt;
&lt;strong&gt;5-10x&lt;/strong&gt; - the #1 factor&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Model choice (for real agents)&lt;/td&gt;

&lt;td&gt;Determines total time (95%+)&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;SDK cold start (Go/Node vs Python)&lt;/td&gt;

&lt;td&gt;3x on first call only&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Connection pool size&lt;/td&gt;

&lt;td&gt;Mild at high concurrency&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Container language&lt;/td&gt;

&lt;td&gt;Zero impact&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Runtime network mode (PUBLIC vs VPC)&lt;/td&gt;

&lt;td&gt;Zero impact&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Client SDK language (warm)&lt;/td&gt;

&lt;td&gt;Zero impact&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;&lt;br&gt;
&lt;p&gt;&lt;/p&gt;


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Test Results&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. Four-Language Echo Comparison (In-VPC)&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;All languages perform identically once warm. The platform routing floor (~80ms in-VPC) dominates.&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Neloh/agentcore-latency-benchmarks/charts/agentcore-latency-comparison.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FNeloh%2Fagentcore-latency-benchmarks%2FHEAD%2Fcharts%2Fagentcore-latency-comparison.png" alt="4-Language Latency Comparison"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. In-VPC vs External Caller&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Calling from within the VPC (via &lt;code&gt;bedrock-agentcore&lt;/code&gt; interface endpoint) is 5-10x faster than calling over the public internet.&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Neloh/agentcore-latency-benchmarks/charts/agentcore-latency-vpc-vs-external.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FNeloh%2Fagentcore-latency-benchmarks%2FHEAD%2Fcharts%2Fagentcore-latency-vpc-vs-external.png" alt="VPC vs External"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;3. Full Comparison: Echo vs Real Agent (SME + Claude Haiku 4.5)&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Model inference (Bedrock) accounts for 95%+ of…&lt;/p&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Neloh/agentcore-latency-benchmarks" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/" rel="noopener noreferrer"&gt;Bedrock AgentCore Runtime documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/strands-agents/sdk-python" rel="noopener noreferrer"&gt;Strands Agents SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://python.langchain.com/docs/integrations/chat/bedrock/" rel="noopener noreferrer"&gt;LangChain AWS integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Chainlink on Docker: Part 1</title>
      <dc:creator>Sibonelo N.</dc:creator>
      <pubDate>Thu, 29 Jun 2023 06:34:50 +0000</pubDate>
      <link>https://dev.to/neloh/chainlink-on-docker-part-1-4nig</link>
      <guid>https://dev.to/neloh/chainlink-on-docker-part-1-4nig</guid>
      <description>&lt;p&gt;Adding off-chain data to a Blockchain network is not a straightforward process. For a Blockchain network to achieve Byzantine Fault tolerance, all the nodes or peer nodes in the network must unanimously agree on the state of the blockchain, also known as the world state. This means that the ledger, which contains the complete history of transactions, must always be consistent and verifiable by all nodes. No node can add a transaction to the ledger without the agreement of other peer nodes. To ensure resilience, every peer node maintains a copy of the ledger. Therefore, even if a particular node becomes unavailable due to network issues or malicious attacks, other nodes can continue to operate within the blockchain network and handle requests. If a compromised node tries to rejoin the network, it may need to be in-line with the blockchain rules (or policies) or be removed from the network through voting, especially if it continues to introduce conflicting transactions that deviate from the overall world state. In Blockchain, the principle of quorum rules applies, where the majority consensus is crucial, and mechanisms are in place to prevent a central entity from validating every transaction of each node.&lt;/p&gt;

&lt;p&gt;In my own opinion, &lt;a href="https://docs.chain.link/"&gt;Chainlink&lt;/a&gt; seems to be the leading oracle that allows integration of data that is considered off-chain to the Blockchain network. With the consistent trend of Web3 and Generative AI it is important to know what Chainlink is. What is the role of Chainlink in various use cases such as  Decentralized Finance, Non-Fungible Tokens (NFTs), Music and Gaming. In a overly simplified way, basically, an oracle or mainly a "decentralised oracle network" (DON) allows &lt;code&gt;off-chain&lt;/code&gt; data to be integrated to a Blockchain network such as Ethereum Mainnet or the Testnets such as Sepolia. &lt;/p&gt;

&lt;p&gt;The aim of this article is to cover the steps that one would  follow when configuring a Chainlink node locally via Docker. Please use the &lt;a href="https://docs.chain.link/chainlink-nodes/resources/requirements"&gt;link&lt;/a&gt; for the hardware requirements if you aim to set this up within your own machine. The steps  are as follows for this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL database setup&lt;/li&gt;
&lt;li&gt;Details on setting up an Alchemy or Infura free account for Sepolia, getting the API KEY.&lt;/li&gt;
&lt;li&gt;Configure an Testnet environment via docker for Sepolia as well.&lt;/li&gt;
&lt;li&gt;Attempt to fulfil requests with the Chainlink node through a Smart contract written in Solidity.&lt;/li&gt;
&lt;li&gt;Validation of transactions via &lt;a href="https://sepolia.etherscan.io/contractsVerified"&gt;Etherscan&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting up PostgreSQL
&lt;/h3&gt;

&lt;p&gt;You can pull an existing docker for PostgreSQL and setup the following commands to create a database user, password and the database where Chainlink will create the relational databases of what store Chainlink events, transactions and events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name cl-postgres -v $HOME/.chainlink-sepolia/db:/var/lib/postgresql/data -e POSTGRES_PASSWORD=myPostgresPW -d -p 5432:5432 postgres:11.12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the above has been ran, you need to create the USER and database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker exec -it cl-postgres psql -U postgres -c "CREATE USER $USERNAME WITH PASSWORD '$PASSWORD';"

sudo docker exec -it cl-postgres psql -U postgres -c "CREATE DATABASE "chainlink_sepoliadb";"

sudo docker exec -it cl-postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE "chainlink_sepoliadb" TO $USERNAME;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above is crucial as these PostgreSQL will be the database where the tables for Chainlink node are stored.&lt;/p&gt;

&lt;p&gt;You can use the following ways to test if the PostgreSQL database is up and running&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if you have &lt;code&gt;psql&lt;/code&gt; CLI within your local machine, you can run the command &lt;code&gt;psql postgresql://$USER:$PASSWORD@localhost:5432/chainlink_sepoliadb?sslmode=disable&lt;/code&gt; to see if you get logged in to the PostgreSQL shell where the database is the &lt;code&gt;chainlink_sepolia&lt;/code&gt; as mentioned within the command. For an example, see this command below:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.chainlink-sepolia$ psql postgresql://$USER:$PASSWORD@localhost:5432/chainlink_sepoliadb?sslmode=disable
psql (14.8 (Ubuntu 14.8-0ubuntu0.22.04.1))
Type "help" for help.

chainlink_sepoliadb=&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Or you can use &lt;a href="https://hub.docker.com/r/dpage/pgadmin4/"&gt;pgAdmin&lt;/a&gt; in order to connect to your &lt;code&gt;localhost&lt;/code&gt; on port &lt;code&gt;5432&lt;/code&gt; as it was exposed via Docker commands. You can do administrator related tasks on the database via this tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Signup for Alchemy Sepolia Testnet.
&lt;/h3&gt;

&lt;p&gt;You need to get the Websocket URL of your Alchemy application. The &lt;code&gt;.env&lt;/code&gt; file for the Chainlink node will need the Websocket URL one can always use HTTPS URL to interact with blockchain network however for the Chainlink setup, you need Websocket URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the Testnet client.
&lt;/h3&gt;

&lt;p&gt;This is up to you. However, in this tutorial we are using the Sepolia Geth client. Using the free faucets to fund this type of testnet for fake currency seems to be currently supported as Goerli is deprecated. You can do the configuration for Goerli but the tutorial on &lt;a href="https://docs.chain.link/chainlink-nodes/v1/running-a-chainlink-node"&gt;official documentation&lt;/a&gt; places Sepolia network forward and regards Goerli deprecated and might have potential issues when setting up. One suggestion, is to run the commands that produce constant logs via the Unix &lt;code&gt;screen&lt;/code&gt; command so that they execute in the background of each terminal. &lt;/p&gt;

&lt;p&gt;As we did for PostgreSQL, you can configure the &lt;a href="https://docs.chain.link/chainlink-nodes/resources/run-an-ethereum-client"&gt;Geth client&lt;/a&gt; for Sepolia using the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker pull ethereum/client-go:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mkdir ~/.geth-sepolia&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker run --name eth -p 8546:8546 -v ~/.geth-sepolia:/geth -it \
ethereum/client-go --sepolia --ws --ipcdisable \
--ws.addr 0.0.0.0 --ws.origins="*" --datadir /geth&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the container was stopped for any reason, you can restart it with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker start -i eth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can detach from the running client by using the commands &lt;code&gt;Ctrl + P, Ctrl + Q&lt;/code&gt; as we do not want to stop it. Chainlink requires this container on running status in order to connect to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the Chainlink node
&lt;/h3&gt;

&lt;p&gt;Once you have the docker up and running for PostgreSQL, Sepolia testnet and you have setup the hidden files &lt;code&gt;.api&lt;/code&gt; file API KEY for Infura/Alchemy, .password file for your Chainlink UI and a &lt;code&gt;.env&lt;/code&gt; file within a hidden directory &lt;code&gt;.chainlink-sepolia&lt;/code&gt;. The .env will contain all your underlying network configurations such as the ChainID for the Testnet and the LINK address to use for your chainlink node. It might look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOG_LEVEL=debug
ROOT=/chainlink
ETH_CHAIN_ID=11155111
CHAINLINK_TLS_PORT=0
SECURE_COOKIES=false
CHAINLINK_DEV=true
LINK_CONTRACT_ADDRESS=0x779877A7B0D9E8603169DdbD7836e478b4624789
ALLOW_ORIGINS=*
MIN_INCOMING_CONFIRMATIONS=1
ETH_URL=wss://eth-sepolia.g.alchemy.com/v2/RTDG...
DATABASE_URL=postgresql://$USER:$PASSWORD@localhost:5432/chainlink_sepoliadb?sslmode=disable

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

&lt;/div&gt;



&lt;p&gt;You need to make sure that you do not commit the above file to Github or any version control service. You start the chainlink node by running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker run --name chainlink_sepolia \ 
     --network host -p 6688:6688 \
     -v $HOME/.chainlink-sepolia:/chainlink \
     -it --env-file=$HOME/.chainlink-sepolia/.env \ 
      smartcontract/chainlink:1.1.0 local n -p \
      /chainlink/.password -a /chainlink/.api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates logs and push to a local folder in the same hidden directoty called, &lt;code&gt;log.jsonl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the docker containers are up and running, you can visit the URL &lt;code&gt;http://localhost:6688&lt;/code&gt; and you should be able to see the Chainlink UI tool. This is where you should locate the Chainlink key, along with the Job UI console where you would define your HTTP request syntax using TOML.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup a Smart contract within Solidity for a basic HTTP request (will be included in &lt;strong&gt;Part 2&lt;/strong&gt;):
&lt;/h3&gt;

&lt;p&gt;This section will be in &lt;strong&gt;part 2&lt;/strong&gt; of this article. I will discuss the underlying smart contract that is responsible for reaching out an world-wide web service (via HTTPs) to fetch &lt;code&gt;off-chain&lt;/code&gt;. Further I aim to discuss how Chainlink works with the &lt;code&gt;on-chain&lt;/code&gt; smart contracts to make sure the blockchain network remains deterministic. This part would also involve setting up a frontend for the project and cover security best practices.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note that the suggestions made here are purely from my understanding of the Chainlink software and can be corrected where misleading or false. The purpose is to learn and grow in the space of Web3, so comments are welcome for improvements.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chainlink</category>
      <category>docker</category>
      <category>web3</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
