Arc 26.06.3: A Concurrency Fix Worth Shipping Fast, and Homebrew for macOS

26.06.3 is a small patch with one fix that matters and one bit of packaging that a lot of people have asked for. The fix corrects a rare database-routing issue under heavy concurrent writes; the packaging brings native macOS binaries and a Homebrew tap, so brew install arc finally works.
It's a drop-in upgrade. No config change, no schema migration, no breaking API changes. Your existing arc.toml, license keys, and tokens keep working. If you run high-throughput or multi-tenant ingest, this is a good one to take.
The fix: database routing under heavy concurrent writes
Under sustained, high-throughput concurrent ingest, a write tagged with one database could occasionally be stored under a different one. The target database is supplied per request, through the x-arc-database header or the db / bucket query parameter, and under the right timing some of those writes landed in the wrong place.
It shows up with a distinctive fingerprint: the misrouted database name is truncated to the length of the intended one. We found it while backfilling a demo dataset into a database called energy_grid (11 characters) on a server that was also running several other live ingesters, and roughly 60% of the rows scattered into directories named vessels_tra, weather_tra, and system_moni, the leading 11 characters of the other databases being written at the same moment. Coal generation appeared to fall off a cliff in the query results, which is what tipped us off: the data wasn't wrong, it was in the wrong place.
The cause is a string-lifetime detail at the request boundary. Arc's write handlers read the target database (and, on the TLE and bulk-import paths, the measurement) using the web framework's request accessors, which hand back lightweight strings that point into the request buffer and are only valid for the life of the handler. Arc's ingest path holds onto that string a little longer than the handler does: the write buffer flushes asynchronously on a background goroutine, and it uses the string to pick the storage directory for the database. If another request reused that buffer in the gap between the handler returning and the flush running, the bytes changed out from under it. Because the string's length was fixed when it was first read but its contents were overwritten later, the misrouted name came out truncated. Copying the value at the boundary, before it can escape the handler, fixes it completely.
Two honest things worth saying about it.
First, why it stayed hidden. The bug only fires under a specific combination: concurrent writes to different databases, in flight at the same instant, at enough volume for the race to actually land. Most deployments write to a single database, and if every concurrent writer targets the same database, the value that gets overwritten is the value it was already going to be, so nothing visibly breaks. Load tests hammer a single database; the demo ingesters that do use multiple databases run at a sedate pace and rarely overlap in the microsecond window that matters. It took the exact intersection of high concurrency, multiple databases, and high volume, all at once, to make it show. That's a combination a busy multi-tenant deployment will eventually hit, which is exactly why we didn't want to sit on it.
Second, what to check if you might have been affected. If you ran heavy concurrent ingest across several databases on an earlier version and you find rows under an unexpected database or measurement directory, those files are ordinary, intact Parquet. Nothing is corrupted; the data is just filed in the wrong place. It can be re-ingested (or moved) once you're on 26.06.3. Reads and queries were never affected; this only ever touched the write path (MessagePack, native and InfluxDB-compatible Line Protocol, TLE, and the CSV / Parquet / Line Protocol / TLE bulk imports).
The fix ships with regression tests that reproduce the exact truncation fingerprint, so it can't quietly come back.
Homebrew for macOS
Arc now builds a native macOS binary for Apple Silicon (arc-darwin-arm64), alongside the existing Linux binaries, .deb / .rpm packages, container images, and Helm chart. That means there's a Homebrew tap:
brew install basekick-labs/tap/arcor, equivalently:
brew tap basekick-labs/tap
brew install --formula arc(The --formula flag is there because arc is also the name of a Homebrew cask, the Arc browser, so a bare brew install arc after tapping would be ambiguous. The fully-qualified form above has no such ambiguity.)
Then start the server:
arc # listens on http://localhost:8000
arc --helpLike every other release binary, the macOS builds are produced on GitHub-hosted runners and cosign-signed with keyless OIDC, with a .bundle signature sidecar attached for offline verification. DuckDB is statically linked, so the install has no runtime dependencies: it's a single self-contained arc executable dropped into your Homebrew prefix.
The formula installs the standard (non-FIPS) build, which is the right choice for local development and evaluation on macOS. The FIPS variant remains a Linux/CMVP-focused build distributed as a container image and Linux packages. Linux users should keep using the .deb / .rpm, container, or Helm artifacts from the release page.
Operator action items
- Update. It's a drop-in upgrade; no config or schema change.
- If you run heavy concurrent ingest across multiple databases, this is the fix to take, and it's worth a quick look for any rows filed under an unexpected database directory from before the upgrade.
- macOS users: if you previously installed Arc by downloading a binary by hand, you can switch to
brew install basekick-labs/tap/arcand let Homebrew manage updates from then on.
How to update
# Docker Hub
docker pull basekicklabs/arc:26.06.3
# or GitHub Container Registry
docker pull ghcr.io/basekick-labs/arc:26.06.3For binary installations, download 26.06.3 from the GitHub releases page, or use the Homebrew tap above on macOS. For Kubernetes:
helm install arc https://github.com/basekick-labs/arc/releases/download/v26.06.3/arc-26.06.3.tgzThe full long-form release notes are in RELEASE_NOTES_2026.06.3.md on the release branch.
Get started:
Questions? Discord or GitHub Issues.