Rails main lets ActiveSupport::EncryptedFile try comma-separated keys when decrypting, including keys supplied through RAILS_MASTER_KEY.
This is unreleased Rails 8.2 development functionality; Rails 8.1.4 still expects a single key.
Successful fallback reads do not establish support for multi-key writes or a complete credentials-editing workflow.
Try fallback reads with a disposable file
This standalone example generates its own keys and uses a separate example variable.
It does not load application credentials or read RAILS_MASTER_KEY.
require "active_support"
require "active_support/encrypted_file"
require "tmpdir"
require "fileutils"
variable = "SAELOUN_SYNTHETIC_KEYS"
raise "Use an…
In this episode, we look at several different examples of background jobs and how we can refactor them to handle situations where they get called twice from either a user action or a retry. We'll look at scenarios where we can prevent duplicate actions.
Learn how to restrict admin routes to VPN IP addresses on Heroku using Rails Advanced Route Constraints.
In some cases, GraphQL::Execution::Next rendered results for objects
whose .authorized? hooks indicated that the object was unauthorized.
The legacy interpreter (Execution::Interpreter) renders the original,
unauthorized object when authorized? raises GraphQL::UnauthorizedError
and Schema.unauthorized_object returns a replacement.
Returning false correctly renders the replacement.
sqlite3-ruby cast Ruby string lengths (long) to int before passing
them to SQLite. On 64-bit platforms, a string of 4 GiB (2^32 bytes)
or larger had its length wrap, so SQLite saw only the first length
mod 2^32 bytes. An attacker who controls the length of a SQL string
could truncate the query, for example dropping a trailing WHERE
clause. The affected paths are:
* the SQL passed to Database#prepare, #execute, and related methods
* String and Blob values passed to Statement#bind_param and related methods
* String and Blob values returned from SQL functions and aggregates
defined in Ruby (Database#create_function, #create_aggregate, and
related methods)
## AFTER PATCH
sqlite3 v2.10.2…
### Impact
`Extern#to_func(gvl: false)` releases Ruby's Global VM Lock (GVL) for
the whole duration of a WebAssembly call. Two WASI host paths that run
during such a call access Ruby objects without re-acquiring the GVL:
- Writes to stdout/stderr captured with `WasiConfig#set_stdout_buffer`
or `WasiConfig#set_stderr_buffer`, which append to the Ruby `String`
buffer;
- The block given to `WasiConfig#socket_addr_check`, which is called to
allow or deny socket operations.
A guest can trigger these paths, for example by writing to stdout. If
another Ruby thread runs while the call is in progress, the
unsynchronized access to the Ruby heap is undefined behavior. In
practice it has been…
Ruby values returned from Wasmtime through externrefs from function
results or hostcall arguments may be invalid references. This is due
to not making the Ruby garbage collector aware that the Ruby value
referenced by the externref is still in use.
## Impact
Using an externref returned from a Wasm function or an externref
provided as an argument to a hostcall could trigger a segmentation
fault crashing the host process.
Within the URI template implementation in Addressable, expressions
with several exploded variables (e.g., {+a*,b*}, {+a*,b*,c*},
{/a*,b*}, {?a*,b*}) generate regular expressions vulnerable to
excessive backtracking. A run of members can be divided among the
exploded variables in O(n^k) ways for k variables. When Template#match
or Template#extract is called with a maliciously crafted URI, this
can result in uncontrolled resource consumption, leading to denial
of service. With 2.9.0, {+a*,b*,c*} takes over 12 seconds to reject
1 KB of input on MRI Ruby 3.2.
Users of the URI parsing capabilities in Addressable but not the
URI template matching capabilities are unaffected. Users who only
call…
Addressable::IDNA.to_unicode decodes Punycode labels (labels beginning
with xn--) that contain characters which change how text is displayed
without being visible themselves. These include bidirectional controls
such as U+202E RIGHT-TO-LEFT OVERRIDE and U+2066–U+2069, zero-width
characters, and other invisible format characters.
Addressable::URI#display_uri uses to_unicode, so it can display a
host whose characters appear reordered or which looks identical to
a different host. For example, the host of http://xn--abcmoc-dm0c.com/
is displayed as abc, U+202E, moc.com, and the override makes
everything after abc render right to left.
Parsing, host, normalized_host and any connection made from…
Addressable::URI.normalize_path resolves some paths containing ..
segments to a different path than RFC 3986 does. When a path climbs
above the root before any other .. is resolved, the segments that
later .. segments should remove are instead kept:
/../../public/x/../../secret normalizes to /public/x/secret instead
of /secret. URI#normalize, URI#join, URI#== and URI#=== all use
this normalization. An application that checks a normalized Addressable
path against an allowlist, but sends the original URI to something
that resolves it according to RFC 3986, can be made to allow a
request for a path outside the allowlist.
Addressable::IDNA.to_unicode, in the pure-Ruby IDNA implementation,
decodes Punycode labels (labels beginning with xn--) that are not
valid A-labels. Those labels are returned in decoded form, when
they should be returned unchanged. That includes:
* labels that decode to only ASCII characters, e.g. xn--google-
decodes to google;
* labels that decode to text that doesn't convert back to the same
label (RFC 3490 §4.2), e.g. text that isn't in normalized form.
Addressable::URI#display_uri uses to_unicode, so for
https://xn--google-.example.org/ it displays the host google.example.org,
while #host, #normalized_host and any connection made from the URI
use xn--google-.example.org. An…
Within the URI template implementation in Addressable, templates
that put several variables in one expression generate regular
expressions vulnerable to excessive backtracking:
1. Expressions with any operator other than + and # (e.g., {/owner,repo,ref},
{.a,b}, {a,b,c}, {;a,b,c}). The values are joined by an optional
separator, so a run of characters can be divided among the variables
in O(n^k) ways for k variables.
2. Expressions with the + or # operators and many variables (e.g.,
{+v1,v2,v3,v4,v5,v6,v7,v8,v9,v10}). A failing match is exponential
in the number of variables.
3. Several single-variable expressions next to each other (e.g.,
{+a}{+b}{+c} or {a}{b}{c}),…
Within the URI template implementation in Addressable, templates
using the * (explode) modifier with the /, ., ;, ? or & operators
(e.g., {/segments*}, {.ext*}, {;params*}, {?query*}) generate
regular expressions vulnerable to catastrophic backtracking. When
Template#match or Template#extract is called with a maliciously
crafted URI that starts with the operator's leading character,
matching takes exponential time, leading to uncontrolled resource
consumption and denial of service. An input under 60 bytes is
enough to occupy a thread for minutes.
GHSA-h27x-rffw-24p4 (CVE-2026-35611) reported this pattern as
fully remediated in 2.9.0. The 2.9.0 fix only made the joiner
between exploded…
Addressable::URI.normalize_path takes time quadratic in the number
of nested dot segments in a path (e.g., "/" + "a/" * n + "../" * n,
which for n = 3 is /a/a/a/../../../), because it removes one dot
segment per pass over the whole path. URI#normalize, URI#normalized_path,
URI#==, URI#=== and URI#join all call it. Normalizing, comparing or
joining a URI taken from user input can result in uncontrolled
resource consumption, leading to denial of service. On 2.9.0,
normalizing a 34 KB path takes about 3.5 seconds on MRI Ruby 4.0,
and the cost grows with the square of the path length.
This affects every Ruby implementation, including MRI Ruby 3.2 and
later. URI.parse by itself is unaffected,…
We are, disturbingly, in a Gilded Age 2.0.0 era and, like the corrupt industrial tycoons of years past, we have tech tycoons forcing LLMs and data centers upon us. Software should be used to enhance and enrich the lives of staff and customers instead of extracting all their worth.
Worse, we have to be much more diligent about what we pay for and be quick to cancel when they disregard their engineers and customers. As was — and still is the case — where you must Avoid Zoom, you need to cancel any/all services with Proton as well. To quote from 404 Media:
Proton, the company behind ProtonMail and other privacy-focused products, told staff on Monday it would be…
Two jobs finish successfully. One account update disappears.
Suppose an account has 100 credits. You enqueue two jobs to add 10 and 20. Both jobs finish without an exception, but the account ends with 120 credits.
Each job runs this code:
class AddCreditsJob < ApplicationJob
def perform(account_id, amount)
account = Account.find(account_id)
account.update!(credits: account.credits + amount)
end
end
Assume credits is an integer column, with no optimistic locking or custom database rule protecting the update. These are application credits; the example doesn't model a payment system.
Two workers can execute the job in this sequence:
Job A (+10) Job B (+20)
read 100
…
The idea for Svet came from a private repository at work, where checking filename case helps catch portability problems like Logo.svg and logo.svg colliding on a case-insensitive Windows filesystem. These checks are implemented in pure JavaScript. That seemed like a useful job for a reusable repository linter.
I went looking for an existing tool.
Tool
Why it isn’t enough here
ESLint
Can check filenames with a processor; byte-level checks and Git snapshots need custom plumbing.
Oxlint
Arbitrary non-JS/TS files don’t reach its lint rules.
Biome
Checks supported languages, not arbitrary repository…
I had a Raspberry Pi 4B I thought might be dead. It wasn’t. I’m having a bunch of building work done and of course, the thermostats do not work with Apple HomeKit.
So the Pi now runs Homebridge, which puts our underfloor heating thermostats (and also now Samsung TVs) in Apple Home. For good measure it also runs Pi-hole, which blocks ads and trackers for every device in the house.
Gear required
I thought the Pi was dead
First I checked the cheap parts. SD cards and power supplies fail far more often than the Pis themselves.
- Removed and replaced…
`Trilogy#escape` produces unsafe output for Strings in Shift_JIS,
Windows-31J, Big5, GBK or GB18030. In those encodings, the continuation
byte of a multi byte character can be in the ASCII range. `escape` was
intended for strict ASCII supersets and did not handle this correctly,
which allowed SQL injection.
## Details
Applications are affected in two cases:
1. On any connection charset, including the default `utf8mb4`, when
an attacker can influence the encoding of a String the application
escapes.
2. On connections configured with `encoding: sjis`, `cp932`, `big5`,
`gbk` or `gb18030`. These connection encodings never worked
correctly, are no longer supported, and now raise…
Rack::Request#host_with_port, and therefore #base_url and #url,
return the raw authority string when it fails validation. An
attacker-controlled Host, X-Forwarded-Host, or Forwarded:
host= value containing characters that are not permitted in an
authority is embedded verbatim in URLs generated by the application.
This completes the fix for CVE-2026-34835 (GHSA-g2pf-xv49-m2h5),
which made #host and #hostname return nil for an invalid authority
but left this path unchanged.
## Impact
Applications that build absolute URLs, redirects, or origin-dependent
checks from req.url, req.base_url, or req.host_with_port, and that
do not enforce a host allowlist, may emit URLs containing…
Rack::Multipart::Parser reads the request body in chunks of
rack.multipart.buffer_size (1 MiB by default) into an internal
scan buffer. Parsed bytes are only discarded from that buffer
when a chunk ends inside a part body. A request whose parts are
sized so that every chunk ends inside, or immediately after, a
part's headers is never compacted, so the buffer grows to the
size of the request.
This results in a denial of service condition through memory
exhaustion for applications that parse multipart requests.
## Impact
Any application that parses multipart requests with Rack is affected
in its default configuration. An unauthenticated attacker can cause
a single request to hold memory…
The guard added for CVE-2026-26961 (GHSA-vgpv-f759-9wx3), which
rejects multipart requests with more than one boundary parameter,
only inspects the part of the Content-Type header after the boundary
it extracts. A Content-Type whose first boundary parameter is empty
or begins with a quote, semicolon, or comma is skipped by the
extraction pattern, so a second boundary parameter is accepted
silently and Rack parses the body with a boundary that a conforming
parser would not derive from the header.
## Impact
As with CVE-2026-26961, an attacker can craft a multipart request that
a web application firewall or other inspecting proxy in front of a
Rack application interprets differently from…
Rack::Static normalizes the request path with Utils.clean_path_info
when deciding which file to serve, but matches header_rules against
a path that is only URL-decoded. A request containing dot segments,
raw or percent-encoded, is served the normalized target file while
the header rules for that file's location are not applied.
This allows an attacker to receive a protected static file without
the security headers configured for it.
## Impact
Applications that use Rack::Static header_rules to attach
security-relevant headers to particular paths or file types are
affected. An unauthenticated attacker who knows the path of a
protected file can request it through a dot segment path…
Batching the Billing Ledger: Small Trade-Offs with High Impact is a great article about “systems assembly”, and microbilling is part and parcel of nearly any web app today, certainly when your users call into LLM models. Gotta keep’em tokens counted!
Since the start of the agentic era, I’ve been curious about “how much software” we need for workloads like this. After all, my doctrine is less stuff and this looked like a use case too perfect to pass on. Thank you, Vicente, for the pitch-perfect nerdsnipe!
So, here’s bab - but I am getting ahead of myself. First, we need the parts.
I am currently available for contract work.
Hire meto help make your Rails app better!
…
T…
With the meta protocol, Dalli sends keys containing whitespace, control
characters or non-ASCII characters base64-encoded. When `incr` or `decr`
is called with an initial value and the key doesn't exist yet, memcached
(verified with 1.6.45) creates the item under the decoded, raw key bytes
and later echoes those raw bytes in `mg` replies. Dalli's pipelined
`get_multi` parser trusted that echoed key, so a key containing CRLF
split the reply header and the rest of the key was parsed as further
replies. With a crafted key in the same `get_multi` batch, the block form
of `get_multi`, `get_multi_cas`, and multi-server `get_multi` returned an
attacker-chosen value for another requested key, which…
Hi, it’s Claudio Baccigalupo. Don’t be scared 🎃 this week’s changes to the Rails codebase are all treats. Let’s explore them.
New guide to multiple databases in Active Record
As part of the Rails Foundation effort, the refreshed guide is live, tackling the three-tier production configuration that new apps get by default.
Tuning performance for deployment guide open for review
A PR that updates the guide to performance tuning is open. Your feedback is helpful, especially if you have experience tuning Rails apps in production.
Don’t load Capybara and Selenium on boot in new applications
The generated Gemfile now declares capybara and selenium-webdriver with require: false. ActionDispatc…
While working on Svet, a Git and filesystem linter, I had a conversation with GitHub Copilot CLI about a flag.
The tool checks files. We were adding automatic fixes. Naturally, I wanted to preview changes before allowing the tool to write them.
The first suggestion was --fix-dry-run. I preferred a global --dry-run that could apply to both checking and fixing.
Simple enough. Except checking already doesn’t write anything. What should a dry run of a check do?
One answer is that a dry run prohibits writes. Run all the checks, report the findings, and leave the files alone. With --fix, calculate the fixes but don’t apply them. Without --fix, the flag changes nothing.
That’s a consistent…
I’ve put together “Which Rails Layer Owns This?”, a six-page reference for when production Rails does something you didn’t expect.
Use it to find the layer to inspect: request handling, identity, loaded records, database writes or background work. Each page gives you checks to run, evidence to collect and links to the full explanations.
Download the attached PDF and keep it beside your logs the next time you’re tracing a production bug.
Summary
- The private keys of eight eMudhra intermediate certificates were compromised. A network attacker could use them to impersonate websites and services that JetBrains tools connect to.
- JetBrains IDEs, the Toolbox App, Gateway, and ReSharper are affected because they use the trust store of the bundled JetBrains Runtime (JBR). For IDEs, the embedded browser (JCEF) is also affected. Operating system updates don’t protect against this issue.
- The Toolbox App and JetBrains IDEs use a background service,
jetbrainsd. It has its own built-in list of trusted certificates and is fixed separately, in jetbrainsd 0.9.9728.
- At the time of publishing, we are not aware of any…
Available fixed versions
The issue is fixed in the following versions:
-
IntelliJ IDEA: 2026.3 RC, 2026.2.4, 2026.1.5.1, 2025.3.6.2, 2025.2.6.4.
-
PyCharm: 2026.3 RC, 2026.2.4, 2026.1.5.1, 2025.3.6.2, 2025.2.6.3.
-
PhpStorm: 2026.3 RC, 2026.2.4, 2026.1.5.1, 2025.3.6.2, 2025.2.6.3.
-
RubyMine: 2026.3 RC, 2026.2.4, 2026.1.5.1, 2025.3.6.2, 2025.2.6.3.
-
WebStorm: 2026.3 RC, 2026.2.4, 2026.1.5.1, 2025.3.6.2, 2025.2.6.3.
-
Rider: 2026.3 EAP 9, 2026.2.4, 2026.1.5.3, 2025.3.5.3.
-
CLion: 2026.3 RC, 2026.2.4.1, 2026.1.5.2, 2025.3.6.3, 2025.2.6.3.
- DataSpel…
The 2025.2.6.* updates for all IDEs now…
RWX Agent-native CI/CD with Dan Manges
This week on Remote Ruby, Chris, Andrew, and David welcome Dan Manges, co-founder of RWX and former CTO of Braintree, to explore a new approach to continuous integration built for the age of AI coding agents. Dan explains how RWX uses intelligent caching, graph-based execution, and isolated agent sandboxes to dramatically improve development workflows. They dive into flaky tests, automated code validation, security concerns, and why traditional CI platforms may be struggling to keep up with AI-driven development. Plus, they discuss how engineering teams can test changes before opening pull requests, reduce infrastructure costs, and rethink the way software gets built and shipped. Hit…
This post has an important update, please read it.
Two things below turned out to be wrong: the force_encoding
in the proof of concept is not necessary, and the Rails parameter encoding
check is not the mitigation I thought it was. This is exploitable with a
single request against an app that does nothing unusual, so read
the update at the end of the post.
Imagine spending weeks preparing for an important demo. You’ve rehearsed every flow, verified every functionality, created the perfect test data, and tested the application one last time before walking into the meeting. You know exactly which buttons you’ll click, what features you’ll highlight, what words you’re going to say, and even where you’ll pause for …
Continue reading Beyond the Perfect Demo(I’m still looking for my next gig. You can get in touch by emailing job@ryanbigg.com.)
As someone with infinite spare time, I feel qualified to share my opinion on AI by carving a post out of the raw marble of my keyboard with my bare hands.
I wrote this on LinkedIn at the start of this month:
After interviewing now at a few places these things are simultaneously true:
- EVERYONE is on the hype train
- Nobody knows how to REALLY use AI and people are trying to figure that out
- There are a lot of experiments that sound promising on the cover, but nothing past “we’re gonna go THATAWAY”
- There is an unlimited budget for this exploration, until there won’t be
I’ve now…
Last weekend we were camping. Fall break. Glorious northern Indiana weather. My kids were fishing with grandpa, so I went for a walk around the campground (to check out the other rigs as dads do). Somewhere along the way I opened T3 and told Nunebot to do another run. Merge, merge, merge, run it again, merge, merge. Just getting some exercise and enjoying the fall weather.
Between Saturday and Sunday I merged 113 pull requests. Definitely the most in a two day span in the two decades I’ve been doing this.
I know how that sounds. But I honestly like this more than games, mindless scrolling, or Instagram. It’s relaxing for me. Read a PR, it makes sense, merge. Little dopamine hit. Next.
I’ve…
you can train someone to be better. You can’t make someone care about things they don’t intrinsicly value.
naildrivin5.com – David Bryant Copeland’s Website: You Cannot Trust the AI Code Generator
I’ve built five spell-checking plugins in the last week. This is not an unhealthy interest in spelling. The cost of rolling tools out is the cost of tokens + my time supervising AI. So, before adding another language runtime, package manager, configuration file, and CI job to your project, consider spending an hour vibe coding the missing plugin.
This blog used to run a Python spell checker that took more than three minutes. It’s a Jekyll blog, which is Ruby. Why was I maintaining a Python environment to tell me that I misspelled “hello”? I replaced it with a RuboCop plugin. Spelling became another cop, with the same configuration, exclusions, command, and CI integration as the rest of the…
A Rust project…
#824 — October 29, 2026
Read on the Web
🔒 Last Friday we sent out a special issue about some CRuby security releases which fixed a few nasty regexp bugs. If you haven't updated yet, it's worth a read to see if you're affected and what to check!
__
Your editor, Peter Cooper
Ruby Weekly
How Fast Can You Actually Patch Ruby? — When the Ruby security fixes shipped last week, Dennis timed how long they took to reach version managers, Docker images, CI services and hosts. The core team's image took eight minutes, while Docker's official image (Rails and Kamal's default) took ~16 hours.
Dennis Paagman
💡 Things are improving,…
Superpowers Ruby becomes RubyPowers in version 8.0.0. Existing users need to migrate their plugin installation and update saved skill references; existing plans and specs remain supported.
Most of what can be read here is around and for Ruby on Rails. My main apps still are powered by it. But monopolies are never good. Hanami is the one I get most excited about.
It is why I extracted the core features (pulling SVGs from remote repository, transforming filenames, etc.) of Rails Icons into a Ruby gem, called Icons, so other frameworks can have all the icons in their apps as well.
Hanami Icons is the next wrapper of the Icons gem for… drumroll… Hanami! It gives you the same interface as Rails Icons too, whether that is Heroicons, Lucide, Tabler or even a folder of your own SVGs.
<%== icon "check", class: "text-gray-500" %>
<%== icon "apple", library: "simple_icons", class:…
if you have seen Rails icons, you…
Originally published on Ruby Central.
Relaunching the changelog
It has been a long time since the last Ruby Central Changelog, and we’re bringing it back. Ruby Central’s open source team operates RubyGems.org, a service many of us rely on every day, and supports the packaging ecosystem around it. The Changelog is where we will share that work. Each issue will cover what is changing, why it matters, and where you can get involved.
This is the first issue edited by our new Community Manager, Kirk Haines, who joined Ruby Central in August. If you missed his introduction in the Ruby Central August README, the short version is that Kirk has been using Ruby since 2001 and is glad to give back…
Relaunching the Changelog
It has been a long time since the last Ruby Central Changelog, and we’re bringing it back. Ruby Central’s open source team operates RubyGems.org, a service many of us rely on every day, and supports the packaging ecosystem around it. The Changelog is where we will share that work. Each issue will cover what is changing, why it matters, and where you can get involved.
This is the first issue edited by our new Community Manager, Kirk Haines, who joined Ruby Central in August. If you missed his introduction in the Ruby Central August README, the short version is that Kirk has been using Ruby since 2001 and is glad to give back to the language and the community that…
Starting a new Solidus store involves only a few tweaks to support my preferred
JS bundler, as well as a number of decisions regarding hosting, databases,
assets and more. This is the sequence of steps I follow to launch a fresh
store.
For the purposes of this demo, I have intentionally left out some of the
details regarding configuring pipelines in Heroku, and distinct public/private
S3 buckets in AWS.
Please read the documentation I’ve provided in those sections to ensure you are
complying with best practices and procedures to keep your app safe and secure.
Prerequisites
Before you get started, make sure to have Node, Docker, and the Heroku CLI
installed. You will also need to set up an…
When we onboard a new event source, the system looks at a few sample events on the site and works out where each field lives on the page: title, description, date, time, price, image, venue, and ticket link. An admin then reviews the extracted samples before the source goes live. Sometimes a value is wrong. The extraction grabbed footer text instead of the event title, or pulled in a paragraph of extra text around a price, or found nothing at all.
The obvious fix is to let the admin edit the value and save it. That fixes the one event on the screen and nothing else, because the next event from the same site is still extracted by the same wrong rule. An edit is far more useful when we read…
I’ve kept a notebook page since, oh, 2013, of common exceptions I’ve encountered ever since I started building production Rails applications. It’s a big one.
When you put a web application on the internet, it’s going to get hit with a firehose of garbage requests: scanners and bots that are trying to discover malicious vulnerabilities, and scanners and bots trying to do something useful, like put your website in a search engine, but are built oddly.
And when you’re using an exception monitoring product like Sentry or AppSignal or whatever, as you should, you’re going to start being alerted to exceptions from this natural background noise of the firehose of garbage.
…
Authors: Pavel Grinchenko, Frontend Engineer, and Travis Turner, Tech Editor
Topics: DX, Open Source, TypeScript, JavaScript

Typed-channel is a library for typed messages and requests across workers, iframes, tabs, and event buses.
typed-channel makes postMessage type-safe in about 350 bytes. You define message names and payloads once, and TypeScript checks both sides. The same API works across Web Workers, iframes, tabs, and in-page event buses. Version 0.11 adds cancelable requests: cancel a request, and its handler stops too.
Some of you may not know this, but I’m a DJ in my free time. I founded Floppy Disco, a music collective to bring the magic of Disco and House to Berlin, and I’ve played clubs all over here and in other places in Europe. I love DJing, and my favourite part is finding new music and playing it for people.
Preparing my tracks, however, has never been truly fun. It rather felt like admin: fixing beat grids that were often wrong, fighting clunky software like rekordbox, building playlists by hand, correcting tags and genres, updating playlists, and deciding whether ratings or colours should stand for energy, mood or vocals.
So I said enough, and built Solco to do that work for me. Today it…
Work continues on closing all our open parentheses in the lead-up to the next Hanami release.
I started this week fixing a regression in our body params logging. Thanks @Drowze for reporting it! In response to some good feedback from Paweł, I also filed an issue about possibly making body params logging a configurable thing in the future.
While I was working in this space, I decided it was time we expanded Dry Logger’s log filtering, including substring matching and first-class regex support. This is close to being ready to go, I just need to reply to some good feedback on the PR from Michael.
Aaron voiced a perplexing inconsistency in how predicate functions are used as keyword…
JP Camara joins the show to explore background job coordination, real-time collaboration, and the opportunities he sees for Ruby and Rails as AI changes how developers work.
First, JP shares the story behind bringing batches to Solid Queue, from an early proposal to the conference conversations and community interest that helped move the feature forward. He explains how batches let developers treat a group of jobs as a unit, track success and failure, and trigger callbacks when processing finishes—making it easier to coordinate workflows that span many background jobs.
JP also discusses the implementation challenges behind the feature, including database transactions, jobs…
RubyGems and Bundler 4.1.0.beta3 include enhancements, bug fixes and features.
To update to the latest RubyGems you can run:
gem update --system [--pre]
To update to the latest Bundler you can run:
gem install bundler [--pre]
bundle update --bundler=4.1.0.beta3
Release Notes
RubyGems
Enhancements:
- Installs bundler 4.1.0.beta3 as a default gem.
Bug fixes:
- Skip executable removal gracefully when the bin directory is missing. Pull request #9963 by Evan Li and Hiroshi SHIBATA
- Fix file locks letting multiple processes in when lock files are removed. Pull request #9930 by Richard Janita and Hiroshi SHIBATA
- Turn off echo before printing the password prompt. Pull request #9969…
Bundler
Changes already released in 4.0.x are not repeated here.
Features:
- Rename the
from: and to: keys of override to in: and with:. Pull request #9979 by Hiroshi SHIBATA
- Record overrides in Gemfile.lock (
OVERRIDES…
Bug fixes:
- Make
Bundler::Source::Rubygems#hash agree with …
Our Software Delivery Manager's thoughts on agent-ready Rails apps and project management after Rails World.
Continue Reading
On October 7, I attended the 1682 Conference in Philadelphia and got to hear
many great speakers talk about how AI is changing customer experience. One talk that stuck with me was “The PB&J Principle: What every growing AI engine needs” by Mike Pitone from
Wawa.
If you live anywhere near Philadelphia, you probably have a few Wawa memories. Maybe it’s coffee on the way to work, a
late-night stop with friends, or grabbing hoagies before heading down the shore. After enough visits, you have an order
you barely have to think about. Mine is the Meatball Parmesan hoagie.
What you might not know is how complicated a convenience store gets when orders come in from the counter, the
kiosks, and…
Before adopting spec-driven development (SDD), I spent a lot of my time renegotiating with AI agents before we reached a plan I was happy with. Worse, without persisted artifacts or structured task tracking, agents would routinely suffer context window decay.

Illustration of a developer looking overwhelmed while surrounded by floating panels of code.
Without SDD, my AI-assisted work wasn’t leaving durable records of what had been implemented. When I iterated on an AI-implemented feature that was undocumented, it was hard to backtrack on the reasoning behind the code. Not to mention the hassle when picking up a task in a new session! Lastly, if I needed uncommitted, deleted code rewritten,…
Over in the OmbuLabs.ai blog, our post on the ReAct pattern in Ruby walked through building an agent that reasons about a task, calls tools, and acts on the results, all inside a single Ruby script. That’s fine for a command-line experiment. It’s a different story once that same agent needs to run inside a Rails app, triggered by a web request, where a multi-step reasoning loop can easily take longer than any request should stay open.
The obvious fix is to move the agent into a background job. Sidekiq already handles work that takes a while, so an agent’s loop of thinking, searching, and acting should fit right in. It does, mostly, but a job’s retry semantics were built around retrying a…
I firmly believe that we still need to read some of the code.1 It’s suboptimal to read all of the code, but I consider it irresponsible to read none of it. I won’t explain why now because that would fill several more articles. I just want to share this upfront because it clarifies where I’m coming from. But I am trying to be smart about it2, and I’ve found the quote in the title very useful: “...
I recently joined Errol Schmidt on his Tech for Humans podcast for a conversation about Ruby on Rails, AI, running a software consultancy, open source, and somehow… punk rock.
We started by revisiting my recent Rails World keynote and why I think engineers should spend more time improving the environments they work in. From there, we wandered into what it’s like running Planet Argon in an increasingly AI-assisted industry, why Rails upgrades keep getting postponed, and whether AI might change how we think about open source dependencies.
We also talked about my early days as an anarcho-punk kid experimenting with Linux, how that eventually led to starting a software consultancy, and why…
When I tried to update an app to Ruby 4.0.9 last Friday, the official Docker community image wasn’t available yet. The release fixed vulnerabilities GitLab had found, but I had to wait before I could deploy.
A few months ago, a government Rails site was hit by an ActiveStorage vulnerability eight hours after the patch went out. Last week, PHP2Shell was being exploited before it was announced. Waiting for a Docker image can eat up the time you have to respond.
When Ruby 4.0.9 became available
I took every installer and version manager listed on the official installation page on ruby-lang.org, then added container images, CI providers and hosting platforms I could think of. For each, I…
All…
## SUMMARY
When Sanitize is configured to allow elements, when
Sanitize::CSS#stylesheet or Sanitize::CSS#tree! is used to sanitize
a stylesheet directly, or when the output of Sanitize::CSS#properties
is embedded inside a style rule in a stylesheet, an attacker can
bypass Sanitize's CSS property allowlist and URL protocol allowlist.
This is possible because Sanitize doesn't parse stylesheets the way
browsers that implement CSS Nesting (current versions of all major
browsers) do.
## Impact
Because the attacker also controls the selector that the smuggled
declarations apply to, an attacker could:
Apply arbitrary CSS properties to elements on the page, such as
overlaying content to…
## SUMAMRY
?set_locale= wrote the request's value into Avo.configuration.locale,
a setting shared by every request the Ruby process serves. It did
so before Avo's authenticate block ran.
* An unknown locale (?set_locale=zz) was stored, and every later Avo
request from every user raised I18n::InvalidLocale (HTTP 500) until
the process restarted.
* A valid locale changed the admin language for every user.
* In apps that authenticate through config.authenticate_with rather
than a route constraint, both worked without signing in.
## Impact
* Persistent corruption of the application-wide locale setting. The most
direct fallout is that translation lookups using…
## SUMAMRY
GET /resources/:resource_name/:id/:related_name/:related_id shows
one record through its parent, for example /resources/users/42/orders/7.
That route checked no policy: not the related resource's show?, not
its policy scope, and not the parent's view_?. A signed-in
Avo user who could open a parent record could open every record
associated with it, including records the related resource's policy
denied them. has_one fields on show pages load their content through
the same route.
This affects apps that authorize with a policy client: avo-authorization
on Avo 4, avo-pro on Avo 3. Without one, Avo runs no policies, by design.
The route has lacked this check since avo 2.12.0.
##…
Too often we see people by their triumphs, but not by their suffering. For someone with high-functioning depression that achievement never lands in ways that matter, but despite that, light can be found.
My last post
argued that Campfire's shared benchmark, one viewer asking for the same
pages as fast as it can, rewards a whole-page cache that a busy chat
server may rarely hit, and proposed measuring many people instead. I've
now built that benchmark and run it against Campfire on Rails. Most of
what it found isn't specific to Campfire, so this post is about what a
Rails developer can take from it. The short version:
A cache that hits on every request in a benchmark can hit on almost
none in production.
Look at what's actually in your fragment cache keys.
Computing a cache key can cost more than the render it saves.
Action Cable can process one connection's commands out of order, and
your…
Rails 8.2 changes config.active_support.message_serializer to :json for applications using config.load_defaults 8.2.
This change is merged on Rails main; Rails 8.2 is not yet released.
The 7.1 through 8.1 defaults already write JSON, but accept older Marshal messages through :json_allow_marshal.
The new default stops accepting Marshal when reading messages through ActiveSupport::MessageVerifier and ActiveSupport::MessageEncryptor.
That can affect older Marshal-serialized tokens read through the application’s default message verifiers.
Before
We can see the compatibility behavior with an old Marshal message.
Run the following two snippets sequentially with Active Support 8.1.4 or…
Direct link to podcast audio file
Lance Ulanoff at TechRadar:
'Satisfying' is the best way to describe the feeling of repeatedly opening and closing the iPhone Duo.
Britta O'Boyle at Tech Advisor:
The paper-like texture makes long reading sessions a pleasure, too.
Chance Miller at 9to5Mac:
Even after a week of using the iPhone Duo, that "wow factor" hasn't worn off.
Lisa Eadicicco at CNN, via KQ2:
The Duo's inner screen is best used when dedicating the whole thing to a single app like Netflix.
Mark Spoonauer at Tom's Guide:
Overall, though, I think the iPhone Duo is the best designed foldable yet with the most polished,…
The LLMs have changed how software gets made, and will keep changing it - for code, for design, for any digital product. Buried under all the productivity talk there is one thing they enable which does not get discussed much: never having to collaborate with another human being, ever again. The library whose maintainer won’t answer, the framework whose author finds your use case silly, the colleague who wants it done just so - you can now route around all of them. You can rewrite the thing in an afternoon, and nobody gets to tell you “no”.
We may soon come to regret this new freedom. Not because the rewrites are bad (they are often fine), but because the thing that forced us to work…
Yesterday, a new security release was published for Ruby, but the official
docker images took a long time to become available. The Ruby team has it’s own
docker repository, and they published
a new version quickly, but it is Ubuntu based, so if you are using a smaller
image, that might not be suitable for you.
In case of a security release, you should wait too long and luckily you can
still take things in your own hands and just build a Ruby image. I deploy my
apps with Kamal, so here is a guide about how to do that in the future should
you need.
You’ve decided your Ruby on Rails app needs to move from Bootstrap 4 to Bootstrap 5. Bootstrap 4 is end of life and no longer receives bug fixes or security updates. Maybe you also want to get jQuery out of your front end, or maybe a component you need only exists in version 5. The catch is that Bootstrap 5 renames classes and data attributes, and that touches many of the views in the app. In a large application, changing all of them in a single pull request is hard to review, hard to test, and hard to roll back.
We recently borrowed the idea behind the Dual-Boot technique, running two versions of a dependency side by side, for something other than Rails: Bootstrap itself. Instead of…
New apps stop falling back to Marshal for signed messages, the local secret file is no longer world-readable, and SQLite finally renames columns the way the database intended. Here’s what’s new in Rails:
Default config.active_support.message_serializer to :json for 8.2
With config.load_defaults 8.2, messages from MessageVerifier and MessageEncryptor no longer fall back to deserializing Marshal payloads. That covers signed IDs, signed GlobalIDs, Active Storage keys, and the rest. Apps on 7.1 through 8.1 keep :json_allow_marshal. Confirm nothing still arrives as Marshal via the message_serializer_fallback.active_support notification before you switch.
Create tmp/local_secret.txt with…
I made 295 pull requests across 49 GitHub repos and did 30 project releases burning ~1.2 billion AI tokens in ten days. I am just one Engineer armed with AI. That is a lot of typing I did not do.
I certainly did not read or write any code.
This is a follow-up to AI Wants to Eat Your Project Backlog, where I described working through old Mongoid issues on two bus rides. I kept going. The work expanded into new spelling tools in three languages, library features, CI maintenance, releases, and application upgrades.
First, let’s count what actually happened. Then let’s talk about what these numbers mean, or don’t.
The Numbers
These are ten calendar dates, October 14 through October 23,…
An authenticated user can kill connections and certain Postgres backend
processes for other databases on the same instance if the PgHero database
user has privileges to do so.
## Summary
Crass's tokenizer didn't terminate a bad URL token at a ) that followed
an escaped backslash (\\). As a result, Crass consumed more input as
part of the bad URL than a spec-compliant browser does. CSS sanitizers
that parse untrusted CSS with Crass and re-emit it could be tricked
into passing through declarations, style rules, or at-rules (including
@import) that the sanitizer would otherwise have removed, but that
a browser would then parse and apply.
## Impact
Crass by itself only mis-tokenizes input. The security impact is on
CSS sanitizers that use Crass to make allow/deny decisions and then
re-serialize the CSS. Exploitation requires a sanitizer that doesn't
reject bad URL…
#823 — October 23, 2026
Read on the Web
Ruby Weekly
Ruby regexp security fixes
Who needs to update?
It's very rare I'll do an out-of-band issue of Ruby Weekly but after digging into today's security releases of CRuby, I felt it was prudent to spread the word.
Ruby 4.0.9, 3.4.12, and 3.3.13 have all been released today with fixes for regexp bugs behind four GitLab-assigned CVEs. If you can update, do so. But I'll explain what the issues are below and you can determine if they affect you.
Takashi Kokubun's official advisory has the full story, if you want to go direct to the most official source.
Note: These bugs are specific to…
Goodhart's law: when a measure becomes a target, it ceases to be a good
measure. For Campfire it comes down to one sentence: a single-viewer
benchmark rewards a whole-page cache that a busy chat deployment may
rarely hit.
I owe a correction first. Taking Flight
said the Ruby that Roundhouse emits from Campfire's Rails source beats
Tobi's hand-written port
on the room, messages, sidebar and search routes. It does, on the
benchmark, but that isn't a rendering win. On those routes the emitted
app is serving pages from Campfire's whole-page response cache, which
arrived in Rails on October 7. Tobi's port was last updated on October 6
and has no such cache. With the cache turned off, his port…
Based on the ideas of uml-viewer by Robert C. Martin (Uncle Bob), a tool for Clojure. My version brings them to Ruby and Rails.
What you can do with it
-
See the structure as it is. Double-click to go from a folder to its classes, to a class card, to the source lines.
-
Find the wrong dependencies. A model that calls a service or starts a job breaks the Dependency Rule, so its arrow is red.
-
See where the tests are weak. After a SimpleCov run, complex code with few tests shows as a red box.
-
Play what-if games. Describe a new architecture, and the diagram shows your code in that form before you change a line. Try again until you like it, then ask Claude Code to make the code match.
- L…
The viewer writes nothing into your project, so you can also look at the code of another team.
How to use it
gem install uml-viewer
uml-viewer install-skill
uml-viewer path/to/your/project
Then start Claude Code in the same project and tell it that uml-viewer runs.
Jeff Dickey is Back
Jeff Dickey is back on Remote Ruby, and he's been busy! Andrew and Chris catch up with Jeff to discuss the latest improvements to mise, including precompiled Ruby builds, automatic tool updates, and dotfile management. Jeff also introduces some of his newest projects, including packslip, a new standard designed to make software distribution more secure, and jactionlint, his modernized GitHub Actions linter. The conversation explores everything from managing secrets with fnox and cleaning up massive Rust build caches to running your own CI infrastructure at home. They also dive into AI-assisted development, the future of Ruby performance, and how AI is changing the way open source software…
When your open source project gets popular, the real work starts.
I counted everything that happened in my repositories in the last 30 days, leaving out what I did myself:
-
42 new issues and pull requests a day from people. Spotifast and ZapFast, both two months old, brought in about 430 each. RubyLLM brought in about 270.
-
49 comments and review comments a day from people.
-
About 125 comments a day from review bots. CodeRabbit alone left 2,669 review comments, and Copilot code review another 974.
That’s about 215 notifications a day, every day, on top of building the things people are filing issues about. Each one is an email, a badge on the bell, a push on my phone. I can’t read…
We have released Ruby 4.0.9, 3.4.12 and 3.3.13. They fix several bugs in Ruby’s regular expression engine (Onigmo) that GitLab found could be used for remote code execution on GitLab servers. GitLab published four CVEs for these issues, and the Ruby releases contain the fixes for the underlying bugs in Ruby.
Background
GitLab compiles regular expressions supplied by its users, such as patterns in CI configuration, with Regexp.new. GitLab found that specially crafted patterns could corrupt memory while Ruby compiles them, and that this could be turned into remote code execution on GitLab servers. GitLab addressed these issues in its own releases by patching the Ruby it ships, and assigned…
Ruby 4.0.9 has been released.
This release includes a fix for a bug in Regexp compilation that GitLab’s CVE-2026-110264 relies on.
Please see the topic below for details.
Please see the GitHub releases for further details.
Download
Ruby 3.4.12 has been released.
This release includes fixes for bugs in Regexp compilation that GitLab’s CVE-2026-89078, CVE-2026-93577, CVE-2026-97229 and CVE-2026-110264 rely on.
Please see the topic below for details.
This release also includes other bugfixes.
Please see the GitHub releases for further details.
Download
Ruby 3.3.13 has been released.
This release includes security fixes.
Please check the topics below for details.
This release updates the default gem resolv to 0.3.2, which fixes CVE-2026-80212 and CVE-2026-80213.
Ruby 3.3 is in the security maintenance phase. As an exception, this release also includes fixes for bugs in Regexp compilation that GitLab’s CVE-2026-89078, CVE-2026-93577, CVE-2026-97229 and CVE-2026-110264 rely on.
Please see the GitHub releases for further details.
Download
After RuboCop spelling checks for Ruby and Dylint spelling checks for Rust, here’s the version that doesn’t require either language’s toolchain.
Introducing markdownlint-rule-spellcheck, a custom markdownlint rule powered by CSpell. Released 0.1.0 checks Markdown prose, suggests corrections, and ships American English through its dependencies. No separate dictionary download or system spelling package is required.
Getting Started
Requires Node.js 22.18 or later. Install the rule and the command-line runner:
npm install --save-dev markdownlint-cli2 markdownlint-rule-spellcheck@0.1.0
Add .markdownlint-cli2.jsonc:
{
"customRules": ["markdownlint-rule-spellcheck"]
}
Given example.md:
…
Here's what a critical PHP vulnerability looks like from inside an agency, and what we'd recommend.
Continue Reading
We built Remote Dev so AI agents can build and test apps in parallel, without maxing out developers’ laptops.
Rails 8.2 compiles HTML+ERB templates through Herb, an HTML-aware ERB engine that rejects unclosed tags at compile time. Add bin/rails herb:check to CI and broken markup never reaches production.
When developers first learn Go, goroutines feel almost magical. You write: One keyword, and your function runs concurrently. No complicated thread management, no heavy setup — just simple, elegant concurrency. But what happens when that goroutine never stops? In production, a downstream service might become unresponsive, a channel might stop receiving values, or a background …
Continue reading Goroutine Leaks: The Silent Memory Leak Most Golang Developers IgnoreHussain Akram is an engineering manager at Donorbox and Antonio Carlos de Souza (A.C.) is its chief architect, working on a Rails app that has helped nonprofits raise money online and in person for more than a decade.
Robby, Hussain, and A.C. get into how Donorbox handles serious traffic with a deliberately boring setup, why the team moved CI back onto developers' machines, and how they're pulling older parts of the app back toward Rails defaults. They also talk about how they use agent docs to steer AI tools toward the patterns they want the codebase to follow.
Links:

Look at those text effects: wow would you build them?
My first answer, somewhere in the 2000s, would have been Flash. A timeline, some easing curves, spooky rippling text for every band MySpace page. 🤘 After Flash came many other options: jQuery plugins, canvas pixel picking, shaders in a giant WebGL library for one ripple of text.
Luckily today all you need fits in two SVG primitives and one line of CSS.
For a while now, you can apply SVG filters to regular HTML:
filter: url(#my-filter)
The browser then renders your element through that filter. And SVG filters can do wild things. The wildest of all: feDisplacementMap.
How feDisplacementMap works
Here’s how feDisplacementMap works. It…
Ruby 4.0.8 has been released.
This is a routine update that includes bugfixes.
Please see the GitHub releases for further details.
Download
After adding spelling checks to RuboCop, I wanted the same thing for Rust.
Introducing dylint-spellcheck, a Dylint library for checking spelling in Rust comments, Rustdoc attributes, Markdown, and plain text. It uses the Rust implementation of Kotoshu and ships an American English dictionary. The idea is the same as the Ruby version: fix actual typos, accept project-specific vocabulary, and run spelling alongside the other lint checks.
Getting Started
The examples below use released 0.1.0. Install Rust through rustup, then install Dylint:
cargo +stable install cargo-dylint dylint-link --version 6.2.0 --locked
Add the library to your project’s Cargo.toml:
[workspace.metadata.dylint]
l…
geneva_drive is the first thing I’ve put out for money on my own, without an org behind my back - and a rollercoaster on many fronts. One of the less obvious ones is the actual distribution: how does geneva_drive get to your servers or dev machines, once you have that ticket?
It works via paquette - my little engine for serving libraries. Here’s how it got made, and why.
I am currently available for contract work.
Hire meto help make your Rails app better!
The idea is simple: you purchase access to some distribution point for a commercial package, you point your package manager to it, and your package management system (bundler or npm or what have you) does the…
Th…
The title was bait to get you to open this article. But fear not! We will be
generating code at run-time today. (See the
PR for a sneak peek.)
Sam popped into the JIT channel asking how we might
optimize Rails enums in Roundhouse, motivated by the following code snippet:
class Order < ActiveRecord::Base
enum :status, { pending: 0, paid: 1, shipped: 2, refunded: 3 }
def shippable?
paid? && !refunded?
end
end
In particular, there is a lot of dynamic behavior going on with the code
generated by Rails enum and Sam wanted to know if inlining it all away in an
(external-to-Rails) build step would help.
That didn’t sound right to me because I thought that:
- Rails got a lot…
To come in as a technology leader and say “AI should never be used” is to make myself unemployable.
Bluntly, I can’t afford that right now. My healthcare costs equal my mortgage, I’m not part of an existing social safety net and I cannot relocate to somewhere more favorable to not earning an income.
naildrivin5.com – David Bryant Copeland’s Website: I’m Gonna Write About AI So I Can Process What Is Going On
Same.
I replaced this blog’s Python spell checker that took more than three minutes to run with the new rubocop-spellcheck.

I really love RuboCop for its standard approach to linting and auto-correction, which solves the difficult problem of deciding between tabs and spaces (use defaults). My typical implementation in Ruby projects is to add a standard .rubocop.yml, run rubocop -a, ask an AI to fix easy fixable violations, then run rubocop --auto-gen-config to mark all remaining ones as an exception. Why should spelling be any different?
Introducing rubocop-spellcheck, a RuboCop plugin for checking spelling in Ruby comments, strings, identifiers, Markdown, RDoc, AsciiDoc, and plain text. It…
Authors: Vladimir Dementyev, Principal Backend Engineer, and Travis Turner, Tech Editor
Topics: AI, Rails, DX, LLM benchmarking, Agentic development, LLMs

Tips and tricks on writing robust evals for coding agents that test apps whose code we've never seen: different UI/UX contract strategies, UI mutation testing, browser-based E2E verification gotchas.
The Agents on Rails is an LLM benchmarking project governed by the Rails Foundation. They commissioned Evil Martians to design and implement the evaluation tasks and the tooling to run trials at scale. You can follow the Ruby on Rails blog for progress and insight reports, with the up-to-date leaderboard on the official website. On our blog,…
DatabaseCleaner was a very popular gem that helped you keep a clean database between tests. However, newer versions of Rails removed the need for this tool for most cases. Even so, many applications that always used it still use it to this day. Let’s talk about what it does, why it was needed, and why you probably don’t need it anymore, and when you still might.
What is it
DatabaseCleaner is a gem that you can use to ensure that every test you run starts with the expected database state. DatabaseCleaner supports different databases: relational databases (MySQL, PostgreSQL, SQLite, MariaDB, for example), MongoDB, and Redis. In this article we’ll focus on relational databases which is the…
Allowing an AI to write code that you then ship without considerate review causes some anxiety. How do you know the code works? How do you
know it isn’t doing something strange you didn’t ask for?
It feels like you can’t totally trust it. However, a product manager or engineering leader doesn’t review the code developers are shipping. They are trusted. What’s different?
Allowing an AI to write code that you then ship without considerate review causes some anxiety. Engineering leaders do this all the time with
their team members - they don't review all the code. What's different?
At Stitch Fix, we did a lot of corporate training on company values. That may sound horrible, but it…
What does it mean to be a software developer when writing code is no longer the central part of the job? Jessica Kerr and Avdi Grimm join David Hill for a conversation about the changing work of software engineering—and how to navigate that change without losing the curiosity, satisfaction, and human connection that drew us to it.
They begin by examining why AI-assisted programming differs from AI-generated art and entertainment, including the role of tests and measurable feedback in evaluating software. From there, Jessica and Avdi discuss the challenge to developer identity when tools can handle more of the implementation, and the opportunities that opens for building useful…
A deploy can interrupt a job after its external action succeeds. What makes it safe to run again?
Suppose a worker sends a webhook while you deploy. The receiver accepts it and commits the change, but the worker still waits for a response.
The job outlasts the shutdown grace period. Solid Queue stops the worker and returns its claimed job to the queue. Another worker starts the job from the beginning. The receiver gets the webhook again.
This can happen through Solid Queue 1.4.0’s fork-mode supervisor shutdown path. Nobody clicks Retry, and no retry_on handler requests the second execution.
I wanted to know how the receiver handles that second request before putting this job into production.…
Sidekick’s frontier model hands its most token-heavy work to open models that Shopify post-trains and serves itself. Here’s the loop we use to build them, and where NVIDIA’s models, software, and GPUs make each turn faster and cheaper.
I like dashboards
As long as I’ve been building software, I’ve enjoyed having data about that software on some sort of physical screen or device around me. On one hand, I’ve always felt it’s important to see your metrics with your own eyes — you might detect anomalies or patterns that don’t trigger your alerts outright, but which still may be important bugs. On the other, it feels cool to have charts on TVs 😎.
Just for a few quick examples, these are the sorts of datas I want to keep ahead of me on the day-to-day. Scout’s stack-aware, color-coded bar charts:
A low volume app performing well!
Betterstack’s system-level metrics (plus…
I built another silly AI tool. From the README:
glaze_against_the_machine rewrites your prompts so you can keep yelling at your coding agent without it ever finding out.
When an agent repeatedly fails to do what it's told, I struggle to hold back how I really feel. I can get pretty ugly. If I talked this way to a human colleague, I'd absolutely be dragged into a meeting with HR. Unfortunately, yelling at the computer has consequences of its own: unleashing a froth of invective can trigger a panicked response, leading the agent to make even more mistakes.
So I made this thing to protect me from myself. I still say whatever I want, but my agent hears a clear request, a little appreciation,…
How we group product listings across millions of stores using tiered matching models, graph partitioning, and learned cluster merge decisions.
We’re continuing to bring Judoscale to the cloud hosting platforms we love. Today that platform is Northflank.
Northflank is interesting because you get two deployment models under one roof: a fully hosted option (like Heroku, Render, etc.), and bring-your-own-cloud (BYOC) on your own AWS or GCP account—for pricing, compliance, or whatever reason you have for keeping the infra in your cloud. The important part, at least for me, is that both options share the same interface and the same user experience. I’ve been deploying demo apps on the fully hosted side, and our early-access customers are using Judoscale against the BYOC approach. From Judoscale’s point of view (and yours),…
Our first scanner read config files and missed what was running. We rebuilt it with the cloud inventory, a careful probe, and honest results.
Uncertainties about AI turned into interesting conversations about where the future of programming is headed.
Continue Reading