W44: 19–25 October 2026. By Nicolas Dao · published . RSS

Patch Node, rotate your keys, and stop buying a load balancer per service

Seven things worth your time from 19 to 25 October 2026, and three of them are security. Node.js patched a critical bug in its Brotli decoder, a poisoned LiteLLM release stole every key on the machines that pulled it, and a researcher dumped eleven unpatched Tailscale findings. The good news: ECS can now share one load balancer across 25 Fargate services, Claude on Bedrock now returns schema-guaranteed JSON, OpenAI shipped its answer to last week's decision models, and DuckDB 2.0 is out as a long-term release.

98 candidates, 137 searches, 8 research agents, 7 worth your time

This week in 30 seconds

The problem you know, the fix, who ships it, and what it's worth. Each card links to the detail.

  1. 01 No change to my pick. The pain: A bug in the compression library inside Node.js means a malicious server or client can crash, and possibly take over, any Node service that decompresses Brotli data: webhooks, fetched pages, uploads. You don't know which of your functions run a patched Node. The fix: Node.js 22.23.4, 24.22.1 and 26.12.1 fix it. Zip Lambdas on the managed runtime with automatic updates get the fix from AWS without a deploy; pinned functions and container images only get it when you act. Node.js security release for the Brotli decoder (CVE-2026-111497) by Node.js and Google: Critical on paper (9.2), hard to exploit on standard builds, and a free patch. Check your update mode today. Medium risk. The details on Node.js security release for the Brotli decoder (CVE-2026-111497)
  2. 02 Skip. The pain: A self-hosted LLM proxy holds every model provider key you own, on a box with a cloud role. One bad update, pulled automatically through a latest tag, hands all of it to someone else. The fix: Keep provider keys where no third-party package runs at install time: a managed gateway with scoped, spend-capped keys, and AWS Secrets Manager read at runtime. If you must self-host, pin by digest and hash. LiteLLM 1.107.0, a credential stealer published as an update by LiteLLM (BerriAI): The poisoned release was live for under three hours. If you pulled it on 21 October, rotate everything that machine could reach. High risk. The details on LiteLLM 1.107.0, a credential stealer published as an update
  3. 03 No change to my pick. The pain: You put Tailscale on client servers so nobody opens an SSH port. A researcher now says one compromised laptop in the tailnet can turn Tailscale SSH and tailscale serve into root on those servers, and there's no fixed release yet. The fix: Subnet routers aren't in any finding. Update every node to 1.104.2 for this week's separate certificate fix, turn Tailscale SSH off where SSM or OpenSSH can do the job, and tighten the rules where you keep it. Tailworm, eleven unpatched findings in Tailscale by Cyberdione Labs (report) and Tailscale: The default setup (a subnet router into a VPC) stands. Tailscale SSH goes on hold until Tailscale ships a fix. Medium risk. The details on Tailworm, eleven unpatched findings in Tailscale
  4. 04 Worth a pilot. The pain: Every Fargate service you put on the internet gets its own load balancer, about $32 a month in Sydney before a single request, or one shared load balancer whose listener rules and certificates you maintain by hand. The fix: Create one gateway, link it to the cluster, and give each service a three-line connector. ECS builds and runs the shared load balancer, the certificate and the routing rule: up to 25 services per load balancer. Amazon ECS Gateway by AWS: The gateway is free. From the second service on, you stop paying for a load balancer each. Medium risk. The details on Amazon ECS Gateway
  5. 05 Follow-up Watching. The pain: You still pay a chat model to answer yes-or-no questions inside your app (urgent, which team, spam), and last week's alternatives were a startup's preview and a model on Workers AI. The fix: OpenAI's Decisions API, generally available since 22 October, takes your data and typed questions and returns probabilities and a confidence, with output free. It's the incumbent's version of the category. OpenAI Decisions API by OpenAI: The safe-vendor option, at about 2.4 times Jev's price and with no Australian processing. My starting point doesn't change. Medium risk. The details on OpenAI Decisions API
  6. 06 Update Worth a pilot. The pain: You ask Claude for JSON, strip the code fences, parse it in a try/catch, validate it, and retry when a field is missing. The pipeline still breaks now and then, and every retry costs tokens and seconds. The fix: Bedrock now constrains Claude's output to your JSON Schema, so the response always parses and always has the shape you asked for. Through the AU inference profile, the request stays in Sydney and Melbourne. Structured outputs for Claude on Amazon Bedrock by AWS: The parse-validate-retry layer goes away, for Claude data that stays in Australia, at no extra charge I could find. Low risk. The details on Structured outputs for Claude on Amazon Bedrock
  7. 07 Update No change to my pick. The pain: A Lambda that needs a few rows from your Parquet lake either waits seconds on an Athena query loop, or runs DuckDB 1.x, which reads many small files on S3 one at a time. The fix: DuckDB 2.0 reads S3 with asynchronous I/O and prunes Parquet better, and it's a long-term release supported until October 2027. DuckDB 2.0.0 LTS by DuckDB Foundation: The DuckDB-in-a-Lambda pattern gets a long-lived version. Its database files are one-way, and 1.4 LTS ends on 17 November. Medium risk. The details on DuckDB 2.0.0 LTS

01 No change to my pick. Medium risk.

Node.js security release for the Brotli decoder (CVE-2026-111497) by Node.js and Google

Critical on paper (9.2), hard to exploit on standard builds, and a free patch. Check your update mode today.

The pain: A bug in the compression library inside Node.js means a malicious server or client can crash, and possibly take over, any Node service that decompresses Brotli data: webhooks, fetched pages, uploads. You don't know which of your functions run a patched Node.

The fix: Node.js 22.23.4, 24.22.1 and 26.12.1 fix it. Zip Lambdas on the managed runtime with automatic updates get the fix from AWS without a deploy; pinned functions and container images only get it when you act.

What happened

On 21 October, Node.js shipped a security release for a bug in the Brotli decoder it bundles from Google (CVE-2026-111497, nicknamed "Broccoli2Shell"). A crafted Brotli stream makes the decoder keep writing into an 8-byte internal buffer instead of failing. Node.js rates it high; Google, as the authority for the CVE, scores it 9.2 out of 10. It's fixed in Node.js 22.23.4, 24.22.1 and 26.12.1, and in Brotli 1.2.1 (1.1.1 and 1.0.10 on older branches).

Node.js names the attack path plainly: data your app decompresses with node:zlib. The explainer site adds fetch() decoding br responses and the Express 5 body parsers. In practice, that's any webhook, upload or fetched page you don't control. The explainer also reports that the public proof of concept only crashes standard builds, and that no attacks had been seen as of 22 October. So this is a patch-today problem, not a panic.

Where you stand depends on how you deploy

  • Zip Lambda on the managed runtime, update mode Auto (the default): AWS patches the runtime, and your functions pick it up without a deploy. The catch is that I found no AWS bulletin or runtime release note saying the nodejs22.x and nodejs24.x runtimes already carry the fixed builds. Log process.versions.node from one function and you'll know.
  • Update mode "Function update": you get the fix on your next deploy. Redeploy.
  • Update mode Manual (a pinned runtime version): never patched. AWS documents Manual as a temporary rollback. Switch it back to Auto.
  • Container images, on Lambda or Fargate: nothing patches itself. Rebuild on a base image with a fixed Node, redeploy every function, and check the version in the running code.
  • Node.js 20 and older: the Node.js post lists only 22, 24 and 26. Move to 22 or 24.
  • Your own copies: a native Brotli package in node_modules, or Python's brotli, is a separate fix (1.2.1).

On Cloudflare Workers, Cloudflare runs the runtime, so there's nothing for you to patch. It hasn't said which Brotli build workerd uses.

The argument this settles

I stopped running Lambda as container images years ago (the stack), partly because I was tired of upgrading Node on AWS's calendar. This week shows the other side of that complaint. On the managed runtime, AWS's calendar is the one that patches you. With an image, you own the Node binary and the Brotli inside it, and every function stays vulnerable until you rebuild it. For most teams, letting AWS own the patching is the better deal.

My verdict

No change to my pick: zip Lambdas on the managed runtime, updates on Auto. The script in the examples below lists every Node.js function with its update mode. Run it today, fix the pinned ones, and rebuild your images. The risk is medium: critical on paper, hard to exploit, and mostly patched for you, unless you pinned something.

02 Skip. High risk.

LiteLLM 1.107.0, a credential stealer published as an update by LiteLLM (BerriAI)

The poisoned release was live for under three hours. If you pulled it on 21 October, rotate everything that machine could reach.

The pain: A self-hosted LLM proxy holds every model provider key you own, on a box with a cloud role. One bad update, pulled automatically through a latest tag, hands all of it to someone else.

The fix: Keep provider keys where no third-party package runs at install time: a managed gateway with scoped, spend-capped keys, and AWS Secrets Manager read at runtime. If you must self-host, pin by digest and hash.

What happened

On 21 October, litellm==1.107.0 was on PyPI from 11:39 to 13:23 UTC. On Docker Hub, the tags v1.107.0, latest, main-latest and main-stable pointed at a poisoned image from 11:46 to 14:20 UTC. The source tag on GitHub was clean: the release pipeline had been pointed at a lookalike repository.

LiteLLM's own post-mortem traces it back five months. A master key was committed to a public repository on 27 May and never revoked. On 10 October it returned a GitHub token belonging to an organisation owner, and that token was enough to override branch protection and repoint the release.

SafeDep's analysis describes the payload: files that run every time Python starts, including when you run pip. They steal cloud credentials, SSH keys, other processes' environment variables, the instance role and every provider key stored in the proxy's database, and install a backdoor that fetches new code every hour.

That last part is what makes this worse than an ordinary bad package. A self-hosted LLM proxy exists to hold all your model keys in one place.

The same week, the same lesson, twice more

  • Railway disclosed on 21 October that customer environment variables had been accessed and some decrypted. Its advice: roll every variable.
  • OpenCode: last week I couldn't confirm a reported breach. OpenCode's own post on X, quoted by StepSecurity, now describes a "large scale distillation attack" that hit 1.4% of OpenCode Console users with linked Anthropic, OpenAI and Google keys. I couldn't open the post itself, so rotate any key you ever linked to the Console. The OpenCode CLI, my pick, wasn't affected according to its co-founder.

Three companies, one pattern: your keys sat in a system you don't run, next to everyone else's keys.

If you ran LiteLLM

  • Don't run pip in a suspect environment, because it triggers the payload. Look for cook.pth, cook.py, sitecustomize.py and a litellm-1.107.0.dist-info folder, and compare image digests with the bad one (the commands are in the examples below).
  • Rotate everything that host could reach: its IAM role (and check CloudTrail for the role being used from outside your network), every provider key in the proxy's database plus its master and virtual keys, the database password, SSH keys and GitHub tokens.
  • Pin images by digest and packages by hash. LiteLLM gives 1.106.2 as its safe version.

Versus my pick

OpenRouter has nothing for you to install or patch, and each key can carry its own spending limit. It costs 5.5% on credit purchases. Cloudflare AI Gateway's core features are free. A managed gateway is still a third party holding your traffic, but a self-hosted proxy only looks cheaper until an incident forces you to rotate every key you own.

This is how I'd wire it for a client: provider keys in Secrets Manager, read at runtime by the function's role, one OpenRouter key per application with a spending limit, and no key ever pasted into a hosted console.

My verdict

Skip self-hosting LiteLLM unless data residency forces you to. If it does, treat the proxy like the vault it is: pinned by digest, the smallest possible role, and outbound traffic limited to the model providers. The risk is high: anyone who pulled latest that day lost everything on the box.

03 No change to my pick. Medium risk.

Tailworm, eleven unpatched findings in Tailscale by Cyberdione Labs (report) and Tailscale

The default setup (a subnet router into a VPC) stands. Tailscale SSH goes on hold until Tailscale ships a fix.

The pain: You put Tailscale on client servers so nobody opens an SSH port. A researcher now says one compromised laptop in the tailnet can turn Tailscale SSH and tailscale serve into root on those servers, and there's no fixed release yet.

The fix: Subnet routers aren't in any finding. Update every node to 1.104.2 for this week's separate certificate fix, turn Tailscale SSH off where SSM or OpenSSH can do the job, and tighten the rules where you keep it.

What was published

On 25 October, Cyberdione Labs published "Tailworm", a report with 11 findings against Tailscale 1.104.2 and headscale 0.29.5. It was tested from 22 to 24 October and published without waiting for a fix. In groups:

  • Tailscale SSH (findings 1 to 3 and 5): socket forwarding that runs as root, socket replacement, a race on the path allowlist, and an out-of-memory loop.
  • tailscale serve and Funnel (7 to 11): the local API exposed to remote peers through a TCP forward, and guards checked only at configuration time.
  • App connectors (4): approved users can pick any destination, including the cloud metadata address.
  • headscale (6): a denial of service on the self-hosted control plane.

Most of them need an attacker who already has an approved account or a compromised device in your tailnet. None of them is a break-in from the internet, and no finding names subnet routers, the way I use Tailscale into client VPCs.

Tailscale's answer so far

There's no bulletin and no fixed release as of 26 October. There is code: on 25 October, public pull requests (21939 to 21945) moved SSH socket forwarding into a monitor that runs as the user instead of root. That suggests Tailscale treats the SSH findings as real. It's also the same family of bugs as bulletins TS-2026-004 to -010 earlier this year. In 2026, Tailscale's bugs keep showing up in SSH and Serve, the features layered on top of the network, not in the network itself.

Separately, bulletin TS-2026-013 (21 October) covers leaked keys for eight eMudhra certificate authorities, fixed in 1.104.2. Update for that one regardless.

What to do this week

  • Update every node to 1.104.2 or later.
  • List the machines running Tailscale SSH, and turn it off (tailscale set --ssh=false) wherever SSM Session Manager or OpenSSH can do the job. SSM needs no open port and is governed by IAM. Where you keep Tailscale SSH, allow non-root users only, with per-pair rules and check mode.
  • Remove app connectors nobody uses, and require IMDSv2 with a hop limit of 1 on instances.
  • Check your serve config for unix: targets.
  • Use single-use or ephemeral auth keys, and rotate tagged devices on a schedule.
  • On headscale, upgrade to 0.29.6.

My verdict

No change: Tailscale stays my default for subnet routers into client accounts. But I'd stop recommending Tailscale SSH on client servers until Tailscale ships a release with the fix. The risk is medium: low for a plain subnet router, real if you use SSH, Serve or app connectors.

04 Worth a pilot. Medium risk.

Amazon ECS Gateway by AWS

The gateway is free. From the second service on, you stop paying for a load balancer each.

The pain: Every Fargate service you put on the internet gets its own load balancer, about $32 a month in Sydney before a single request, or one shared load balancer whose listener rules and certificates you maintain by hand.

The fix: Create one gateway, link it to the cluster, and give each service a three-line connector. ECS builds and runs the shared load balancer, the certificate and the routing rule: up to 25 services per load balancer.

What it is

ECS Gateway (20 October) isn't a new kind of load balancer. It's ECS running ordinary Application Load Balancers in your account, so you don't have to. A platform person creates a gateway once (subnets, public or internal, optional WAF), links it to a cluster, and each service adds a connector that names its container port. ECS then creates the load balancer, a certificate, a generated hostname, a routing rule, a target group and a security group per service. It adds load balancers as each one fills up (25 services each) and deletes the empty ones.

Before and after

  • Before: each internet-facing Fargate service gets its own ALB, listener, target group, certificate and security groups, wired by hand in IaC. Or you share one ALB and keep its rule priorities straight yourself.
  • After: a three-line connector per service. A new service has a working HTTPS URL as soon as its route turns active.

Cost

The gateway itself is free. In Sydney, an ALB is $0.0252 an hour ($18.40 a month), plus $5.84 a month for the minimum one capacity unit, plus two public IPv4 addresses in two zones ($7.30). That makes about $31.54 per load balancer per month (my arithmetic from the AWS price list):

Services One ALB each With ECS Gateway
1 $31.54 $31.54
5 $157.70 $31.54
25 $788.50 $31.54

Compute doesn't change, and capacity units follow traffic, so a busy set of services pays more than this. The saving is the fixed cost per load balancer, and it starts with the second service.

The limits

  • HTTPS on port 443 only, and routing by hostname only, not by path.
  • The hostnames are generated (*.ecs.<region>.on.aws). Custom domains aren't documented, so keep a dedicated ALB for a client's branded domain until they are.
  • Same VPC, same account, awsvpc networking only, and not for ECS Express Mode services.
  • The gateway's subnets, scheme and listener can't be changed later. To change them, create a new gateway and move the services.
  • Changing a health check replaces the target group, and that fails on rolling deployments. Set the health check when you first connect the service, or use blue/green.
  • Up to 25 services share one load balancer, and its problems. Split gateways by environment.
  • AWS says "all commercial Regions". Sydney isn't named on any page, but it's a commercial Region.

Infrastructure as code: CloudFormation has AWS::ECS::Gateway from day one. Terraform has no resource yet (issue 50573), and Pulumi's aws-native provider hasn't been confirmed. That matters to me: if it isn't in code, it doesn't exist.

Versus the alternatives

Lambda function URLs still win for spiky traffic, because there's no hourly fee at all. API Gateway still wins when you need auth, throttling or path routes. ECS Gateway is for the step I already recommend: when a Lambda is busy all day, move it to Fargate. That step just got cheaper from the second service on.

My verdict

Worth a pilot on internal or non-critical services, through CloudFormation until Pulumi and Terraform catch up. The risk is medium: the saving is real and simple, but the feature is a week old, custom domains are missing, and 25 services share one failure point.

05 Follow-up Watching. Medium risk.

OpenAI Decisions API by OpenAI

The safe-vendor option, at about 2.4 times Jev's price and with no Australian processing. My starting point doesn't change.

The pain: You still pay a chat model to answer yes-or-no questions inside your app (urgent, which team, spam), and last week's alternatives were a startup's preview and a model on Workers AI.

The fix: OpenAI's Decisions API, generally available since 22 October, takes your data and typed questions and returns probabilities and a confidence, with output free. It's the incumbent's version of the category.

Previously: Covered in week 43. Here is what changed since.

What changed since last week

Last week's item was a category that didn't exist in August: decision models. TypeSafe's Jev started it, and Cloudflare's open-weight Clef answered it. This week, OpenAI's Decisions API reached general availability (22 October), sixteen days after its beta. One endpoint takes your text, images or JSON plus typed questions: a predicate (yes or no, as a probability), a choice (one of your labels) or a score (a position on your scale). It returns probabilities and a confidence, never prose. There's one model, gpt-6-luna.

So the category now has a startup's preview, open weights from Cloudflare and a GA product from the biggest vendor in AI, all within six weeks.

Price and residency

Input, per million tokens Output Status
OpenAI Decisions $0.10 free GA
Jev (TypeSafe AI) $0.042 not charged early access
Clef Flash (Workers AI) $0.038 free open weights

OpenAI costs about 2.4 times Jev and 2.6 times Clef Flash. In absolute terms all three are tiny: 10 million tokens of support tickets is about $1 at OpenAI's price. The real differences are elsewhere. OpenAI's regional processing covers only the US and Europe, not Australia. Zero data retention is available to eligible customers. It's not on OpenRouter, so my default gateway can't reach it. And its Node SDK already made breaking changes to the Decisions types on the day of GA.

Jev's bad week

A third-party report on 24 October says a leak exposed every Jev customer's outputs. I found no post from TypeSafe itself. Jev is still early access, so the "play, don't marry" rule I gave it last week already covers this. Until TypeSafe publishes what happened, don't send it personal data.

My verdict

Still watching, and my starting point doesn't change: start with Clef Flash; open weights are your exit. Use OpenAI Decisions if the app already runs on OpenAI and needs zero data retention or a US or European region. Whichever you pick, put the call behind your own predicate / choice / score interface: the three APIs have the same shape, so switching is a thin adapter. The risk is medium: a mature vendor, but a sixteen-day-old product with one proprietary model and no published deprecation policy.

06 Update Worth a pilot. Low risk.

Structured outputs for Claude on Amazon Bedrock by AWS

The parse-validate-retry layer goes away, for Claude data that stays in Australia, at no extra charge I could find.

The pain: You ask Claude for JSON, strip the code fences, parse it in a try/catch, validate it, and retry when a field is missing. The pipeline still breaks now and then, and every retry costs tokens and seconds.

The fix: Bedrock now constrains Claude's output to your JSON Schema, so the response always parses and always has the shape you asked for. Through the AU inference profile, the request stays in Sydney and Melbourne.

What it is

Since 20 October, Bedrock supports structured outputs for every Claude model, through Converse, ConverseStream and InvokeModel. It isn't "JSON mode", which only promises valid JSON. Bedrock compiles your JSON Schema into a grammar and only lets the model produce tokens that fit it, so the response always parses, with the types, required fields and enum values you declared. You pass the schema in outputConfig.textFormat, or set strict: true on a tool.

Before and after

  • Before: a prompt that begs for JSON, code to strip fences, JSON.parse in a try/catch, a Zod check and a retry loop, and still the occasional missing field at 3 a.m.
  • After: pass the schema and parse the result. You still check stopReason (a truncated answer isn't valid JSON) and still validate business rules in code, because some keywords aren't supported.

For Australian clients

Sonnet 5.5 is available through the AU inference profile au.anthropic.claude-sonnet-5-5, which only routes to Sydney and Melbourne. Bedrock's docs say cross-Region profiles support structured outputs with no extra setup. No page names the AU profile specifically, so make one test call before you promise it to a client. The price: regional profiles cost 10% over Anthropic's list price, so Sonnet 5.5 is about $2.20 / $11 per million tokens (my arithmetic). I found no surcharge for structured outputs.

The Anthropic API has had the same feature for a while, at the same list price, with no Australian residency. So the capability is equal, and the choice between them is about where the data goes. That's exactly why Bedrock is on my list.

Gotchas, with fixes

  • The first request with a new schema compiles a grammar, for up to about 90 seconds. Set your client timeout to at least 120 seconds and warm each schema at deploy time. The cache lasts 24 hours, so a schema used once a day recompiles every day.
  • Unsupported keywords return a 400: minimum/maximum, minLength/maxLength, multipleOf, recursion. Enforce those in code after parsing.
  • Every object needs additionalProperties: false, and a schema can have at most 12 optional properties and 16 union-typed ones. Make fields required and nullable, or split a big extraction into several calls.
  • In Converse, the schema is a JSON string; in InvokeModel, it's an object.
  • Citations and structured outputs together return a 400. Use one or the other.

Cloudflare's Clairic, the same day

On 19 October, Cloudflare released Clairic in preview on Workers AI: a model that only extracts typed values from text and images, at $0.10 per million input tokens with no output charge. Cloudflare claims 49% lower cost per pipeline, but that comes from its own test on one claims workflow, against GLM-5.3 rather than Claude. No Region is stated, so it's not an option for Australian client data yet. It's interesting, and I'm watching it.

My verdict

Worth a pilot for document and form extraction where the data must stay in Australia. Bedrock itself stays on watch in the stack until I've run it in production. For an Australian client extracting data from documents, this is where I'd start now: Claude through the AU profile, a schema per document type, and the business rules in code. The risk is low: a GA feature from mature vendors, and the only gap is one test call on the AU profile.

07 Update No change to my pick. Medium risk.

DuckDB 2.0.0 LTS by DuckDB Foundation

The DuckDB-in-a-Lambda pattern gets a long-lived version. Its database files are one-way, and 1.4 LTS ends on 17 November.

The pain: A Lambda that needs a few rows from your Parquet lake either waits seconds on an Athena query loop, or runs DuckDB 1.x, which reads many small files on S3 one at a time.

The fix: DuckDB 2.0 reads S3 with asynchronous I/O and prunes Parquet better, and it's a long-term release supported until October 2027.

What changed

DuckDB 2.0.0 shipped on 21 October as the project's second long-term-support release, supported until at least October 2027. For anyone querying a lake on S3, the headline is asynchronous I/O: DuckDB fetches row groups in parallel instead of one request at a time. Parquet pruning and partitioned writes are better too. It adds a VARIANT type for semi-structured data and Quack, a protocol that lets one DuckDB serve others. The Node client, @duckdb/node-api 2.0.0-r.1, was published the same day.

DuckDB calls the S3 change "dramatically faster", and publishes no number. Benchmark 1.5 against 2.0 on your own queries, in the same Lambda, before you repeat the claim.

Before and after

  • Before: a Lambda that needs a few rows from the lake calls Athena (billed at least 10 MB a query, a start-poll-fetch loop, seconds of latency), or runs DuckDB 1.x, held back by synchronous reads on many small files.
  • After: one SELECT over s3:// inside the function, with no polling and parallel reads. As a rough illustration (my arithmetic, not measured): a query that scans 1 GB in 10 seconds on a 2 GB Arm Lambda in Sydney costs about $0.00027 of compute, against $0.005 on Athena. Athena still wins the big scans, because one Lambda tops out at 15 minutes and 10 GB of memory.

That's still my position in the stack: DuckDB next to Athena, not instead of it.

Gotchas, with fixes

  • Database files are one-way. A .duckdb file written by 2.0 can't be opened by 1.x. If a build job moves to 2.0 while a Lambda layer stays on 1.x, the Lambda breaks. Upgrade every reader before any writer. (Parquet files aren't DuckDB database files, but test your own anyway.)
  • Extensions are built per version, so a layer that bundles 1.x httpfs or iceberg won't load them on 2.0. Rebuild the layer with the 2.0 binary.
  • Single-arrow lambdas (x -> x + 1) are off by default and disappear in 2.1. Rewrite them as LAMBDA x : x + 1.
  • 1.4 LTS ends on 17 November 2026. If you're on it, you have three weeks: go to 1.5 (supported until March 2027) now, or plan 2.0.
  • Quack listens on localhost by default. Don't expose it from a Lambda or a container without TLS and authentication in front.

Who owns it

The DuckDB Foundation, a non-profit, still holds the MIT-licensed project. The core team at DuckLabs joined AWS on 1 September. The 2.0 release notes say nothing about governance, and I've seen no sign of DuckDB inside Athena or Glue yet.

My verdict

No change: DuckDB stays my pick for Parquet queries inside a Lambda. Keep production on 1.5 for a few weeks, and move to 2.0 after its first patch release, all readers first and the layer rebuilt. The risk is medium: a five-day-old major release with a new storage format, softened by long-term support until October 2027.

Looked at, skipped

What else made noise this week, and why it didn't make the cut.

  • Kimi K3.1 Pro by Moonshot AI

    The best model of the week on paper: 55 on Artificial Analysis's index against 56 for Claude Sonnet 5.5, at Sonnet's own price of $2 / $10 per million tokens. Moonshot is its only host, it runs at under half Sonnet's speed, and the open weights are promised by 4 November. Same price isn't a story; I'll look again when other hosts serve the weights.

  • MiniMax M3.1 Flash by MiniMax

    Scores 43 at about $0.22 a task. DeepSeek V4.1 Flash, last week's pick for bulk work, scores 45 for $0.26 with MIT weights. No reason to switch.

  • Lambda Web Functions, one week on by AWS

    Still five Regions and still no Sydney. Nothing changed since last week, so it stays on watch.

  • Lambda MicroVMs in four more Regions by AWS

    Fourteen Regions now, and Sydney still isn't one of them.

  • CloudWatch Omni in Sydney by AWS

    AI-assisted troubleshooting over your logs and traces, now in Sydney, with no price on the launch page. My problem with CloudWatch is the bill, and a chat window on top of it doesn't touch the bill.

  • Agent Skills donated to the Agentic AI Foundation by Anthropic and the Linux Foundation

    Disclosure: I build HappySkills on this format, so I'm glad it's under neutral governance. Nothing for you to change this week.

  • Cloudflare MCP servers drop /sse by Cloudflare

    Old client configs pointing at /sse now fail. Change them to /mcp and move on.

  • Cloudflare Tunnel normalises URLs before ingress matching by Cloudflare

    Becomes the default on 25 January 2027. If your Tunnel routes by path, test your rules before then.

  • createAI replaces the Workers AI and AI Gateway providers by Cloudflare

    Model fallback becomes one parameter and the migration is a rename. Good for AI Gateway, which stays on my watch list.

  • AgentCore Gateway model fallback by AWS

    A headline with no price, caching or limits behind it yet. Cloudflare AI Gateway already does this for free.

  • Resend Forge and Inboxes by Resend

    Resend's own mail server and an inbox API for agents, with vendor claims and no published price. Resend stays my pick; I'll test before I repeat the deliverability claims.

  • OAuth provider for Managed Better Auth (beta) by Neon

    Useful for MCP servers, but Neon Auth still has no SSO or MFA, which is what I'm waiting for.

  • Better Auth 1.7.13 and 1.8.0-beta.2 by Better Auth

    No new advisory this week. Stay on 1.7.x, never below 1.7.7, and leave the 1.8 beta alone.

  • PHP2Shell (CVE-2026-109618 and 109619) by PHP

    Not my runtime, but if you host Moodle or WordPress for clients, patch today: PHP 8.2.35, 8.3.36, 8.4.27 or 8.5.12. Lambda has no managed PHP runtime, so custom runtimes and images need a rebuild.

  • tsrs, a Rust port of TypeScript by Cloudflare and partners

    "Up to 8x faster" is the vendor's own benchmark, and TypeScript 7 is already getting faster on its own. Wait for it to ship.

  • GitHub package firewall (preview) by GitHub

    Enterprise Cloud only. Its cooldown idea is the one to copy anywhere: don't install a release in its first days. LiteLLM's poisoned version was gone in under three hours.

  • Claude Security continuous scanning by Anthropic

    Enterprise seats with token billing, and not available with zero data retention. Not for small teams yet.

  • Google Agent Compute Engine, Data Agent Kit, and OpenAI and Claude on Google Cloud by Google

    Fine products on a platform I don't put clients on. Cloudflare Sandbox stays my pick for running code nobody reviewed.

  • PGX by PGX

    Thousands of throwaway Postgres databases in one process, says the launch post. No docs or repository I could open, and every number is the launcher's own. A launch tweet isn't a product.

  • Upstash Box, Vercel durable-harness and Docker Sandboxes for Harbor by Upstash, Vercel and Docker

    Three more agent sandboxes in one week. The category is crowded and young; Cloudflare Sandbox stays my pick.

  • Capacity reservations for Aurora and RDS by AWS

    You pay for idle capacity to make sure a migration cutover has somewhere to land. Useful once a year, and it makes Aurora dearer, not cheaper.

  • DeepSeek V4.1 Flash on Workers AI by Cloudflare

    The model launched on 17 October and was last week's pick. On Workers AI it's capped at 20 requests a minute, so OpenRouter stays the way to use it.

  • Voxtral 3 by Mistral

    A voice model with prices I could only find in the press. Relevant only to voice-agent builds on Twilio, and not proven yet.

  • Stripe Treasury for agents by Stripe

    Money accounts for AI agents, with an announcement date the press can't agree on. Nothing a client of mine needs this year.

For the geeks

Examples and code for the items above.

Node.js: list your functions and their update mode

Adapted from the Lambda runtime management docs:

# Every Node.js function, its runtime and its update mode (Auto, FunctionUpdate or Manual)
aws lambda list-functions --query "Functions[?starts_with(Runtime,'nodejs')].FunctionName" --output text | tr '\t' '\n' | while read f; do
  echo "$f $(aws lambda get-function-configuration --function-name "$f" --query Runtime --output text) $(aws lambda get-runtime-management-config --function-name "$f" --query UpdateRuntimeOn --output text)"
done

# Put a pinned function back on automatic updates
aws lambda put-runtime-management-config --function-name NAME --update-runtime-on Auto

# Inside the handler, to see what you actually run:
# console.log(process.versions.node, process.versions.brotli)

LiteLLM: check a host without starting Python

From the indicators in LiteLLM's incident post and SafeDep's analysis:

# Files the payload drops (never run pip or python from a suspect venv first)
find / \( -name cook.pth -o -name cook.py -o -name 'litellm-1.107.0.dist-info' \) 2>/dev/null
find / -path '*site-packages/sitecustomize.py' 2>/dev/null
ls /tmp/remote_code_loader.lock /tmp/.pc_once_72129118c59f5636c0bb 2>/dev/null

# Containers: the compromised image index digest
docker image inspect --format '{{.RepoDigests}}' ghcr.io/berriai/litellm:main-stable | grep 1bbcb1443bc9 && echo COMPROMISED

Tailscale: check the version and turn SSH off

From the Tailscale SSH docs:

tailscale version                 # want 1.104.2 or later
tailscale set --ssh=false         # keep another way in (SSM, OpenSSH) before you do this

And, where you keep Tailscale SSH, a policy rule for non-root users on their own devices only:

"ssh": [{ "action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:self"], "users": ["autogroup:nonroot"] }]

ECS Gateway: one gateway, many services

From the AWS News Blog and the ECS docs:

aws ecs create-gateway \
  --name my-team-gateway \
  --infrastructure-role-arn arn:aws:iam::123456789012:role/ECSGatewayRole \
  --configuration '{"HostSharedAlb":{"networkConfiguration":{"subnets":["subnet-080779f9bd887757a","subnet-03d5b2fead6bc6258"],"ipAddressType":"ipv4"},"scheme":"internet-facing"}}'

aws ecs associate-gateway-with-cluster \
  --gateway my-team-gateway \
  --cluster arn:aws:ecs:ap-southeast-2:123456789012:cluster/my-cluster

# Each service: name the container port mapping to expose
aws ecs update-service \
  --cluster my-cluster --service my-service \
  --gateway-connectors '[{"portName": "web"}]'

OpenAI Decisions: route a complaint

The request body from OpenAI's Decisions guide:

{
  "model": "gpt-6-luna",
  "input": "<complaint text>",
  "questions": [
    {
      "type": "choice",
      "name": "department",
      "instructions": "Which department should handle this complaint?",
      "choices": [
        { "value": "billing", "description": "Payments, invoices, and refunds." },
        { "value": "other", "description": "Requests outside these categories." }
      ]
    }
  ]
}

Bedrock: guaranteed JSON from Claude, in Australia

Adapted from the Bedrock structured-output docs (they show the raw Converse request; this is the JavaScript SDK v3 version of it):

import { BedrockRuntimeClient, ConverseCommand } from '@aws-sdk/client-bedrock-runtime';
import { NodeHttpHandler } from '@smithy/node-http-handler';

// The first call with a new schema can take ~90 s to compile: raise the timeout.
const client = new BedrockRuntimeClient({
	region: 'ap-southeast-2',
	requestHandler: new NodeHttpHandler({ requestTimeout: 120_000 }),
});

const schema = {
	type: 'object',
	properties: { title: { type: 'string' }, summary: { type: 'string' }, next_steps: { type: 'string' } },
	required: ['title', 'summary', 'next_steps'],
	additionalProperties: false,
};

const res = await client.send(new ConverseCommand({
	modelId: 'au.anthropic.claude-sonnet-5-5', // AU profile: Sydney and Melbourne only
	messages: [{ role: 'user', content: [{ text: 'Extract the title, summary and next steps from: ...' }] }],
	inferenceConfig: { maxTokens: 1024 },
	outputConfig: {
		textFormat: {
			type: 'json_schema',
			structure: { jsonSchema: { schema: JSON.stringify(schema), name: 'data_extraction' } }, // a JSON string in Converse
		},
	},
}));

if (res.stopReason !== 'end_turn') throw new Error(`Not complete: ${res.stopReason}`); // max_tokens means truncated JSON
console.log(JSON.parse(res.output.message.content[0].text));

DuckDB 2.0: Parquet on S3 from a Lambda

Adapted from DuckDB's Node client and S3 docs:

import { DuckDBInstance } from '@duckdb/node-api'; // 2.0.0-r.1

const instance = await DuckDBInstance.create(':memory:');
const connection = await instance.connect();

// Lambda has no home directory: set one before installing extensions or creating secrets.
await connection.run("SET home_directory='/tmp'");
await connection.run('INSTALL httpfs; LOAD httpfs');
await connection.run("CREATE OR REPLACE SECRET s (TYPE s3, PROVIDER credential_chain, REGION 'ap-southeast-2')");

const result = await connection.run("SELECT * FROM 's3://your-bucket/your_file.parquet' LIMIT 10");
console.log(await result.getRowObjectsJson());

A new edition every Monday.

Subscribe by RSS

Window 19 to 25 October 2026 (UTC). Scanned the AWS What's New and News Blog feeds, the Cloudflare changelog and blog, InfoQ, Hacker News, the release notes and advisories of every tool in the stack, X and Google News, the week's new models on OpenRouter, Hugging Face and Workers AI, plus open searches across every concern in the catalog: 98 candidates, 7 kept. Reddit only through search snippets, as usual. Not exhaustive: if it matters and it's missing, tell me.

Want this stack in your AWS account?

Cloudless Labs is a Sydney consultancy. We migrate on-premises systems to AWS, build serverless apps on this stack, and coach teams to ship with Claude Code and Codex.

Contact Us

For general inquiries, please contact us at:

For e-learning capabilities, please contact: