nh2
It depends.
Mostly on how much rebuilding it needs (e.g. if it's a "leaf" package, or one many packages depend on).
The merging of security fixes is usually very good, also because it is so easy for anyone to just make a PR.
The security team also seems pretty competent and fast.
As a sibling commenter says, it is also extremely easy to just apply patches to your own system in general, usually with a few line of easy code max. So you can fix systems without dependence on distro maintainers.
In contrast to e.g. patching a `.deb`, you can declare the code such that the patch will still be used even if the distro releases a new package; you can carry the patch forward, and don't need to choose between {not having the patch because the distro lacks it} and {not having future security fixes because you pinned your custom .deb version}. NixOS will rebuild any future update, applying your patch to it. That's a big benefit, because it makes "out-of-tree" custom patches very maintainable.
Due to declarativeness, you can easily roll out your fix on lots of machines.
Also, the "SBOM" (software bill of materials) part is quite good in NixOS. It's very easy to determine which package uses what dependencies.
The only real drawback is CI build time when a high-dependency package needs fixing.
Due to the way Nix works with its immutable hash DAG of package dependencies, a package change will trigger a full rebuild of all packages that recursively depend on it.
For example, if you change 1 line in glibc, or libpng, or curl, or (recently) brotli, the entire distro needs to be recompiled from source ("rebuild the world"). Some of the packages, such as Chromium, can take many hours to rebuild individually. Rebuilding all-of-NixOS can take days.
In distros that can mutate packages without triggering dependency rebuilds, updating 1 line in e.g. glibc, will only rebuild that package, allowing to theoretically distribute such security updates within minutes (if done, see Ubuntu counter-example).
The mass-rebuilding is done by NixOS's binary-cache build farm. A new NixOS update is generally only released once the build farm has fully built all dependents. (One can also opt into a "small" channel that releases as soon as only a few core packages are built, which gives you security updates faster for those. But if you do that, your computer will next start compile all huge packages such as Chromium, in parallel to the NixOS build farm already doing that. So usually people don't.)
For the recent brotli CVE-2026-111497, the timline was:
2026-10-21 node.js releases its fix for node2shell (caused by brotli)
2026-10-21 19:27 https://github.com/google/brotli/releases#release-v1.2.1
2026-10-22 brotli CVE-2026-111497 gets published
2026-10-22 06:51 PR "brotli 1.2.1" https://github.com/NixOS/nixpkgs/pull/577208
2026-10-22 08:25 PR merged to "staging" that will become rolling "nixos-unstable" in the future
2026-10-23 created https://tracker.security.nixos.org/suggestions/by-id/60353
2026-10-23 created https://github.com/nixos/nixpkgs/issues/577796
2026-10-28 CI has built a nixos-26.05 update that includes it:
https://hydra.nixos.org/build/351243680
This is the point where users can install it.
2026-11-02 CI for rolling-release nixos-unstable is still not built, 2 weeks later:
https://github.com/NixOS/nixpkgs/pull/577208#issuecomment-6573335016
So in summary: The PR got made within 7 h
Review and merge happened within 2 h
CI took additional 6 days for stable NixOS 26.05
CI for rolling nixos-unstable is still not finished after 10 days post-merge
For our startup, I rebuilt the slice of the world we use on a 16-core CPU within a day or so, without waiting on the NixOS build farm to build all of NixOS, so we got the update significantly faster.Also note that just patching a library in your distro is often not enough. For brotli, lots of upstream package vendor brotli's code. NixOS contributors seem to be quite good at looking at underlying issues, e.g. there's this issue "Tracking vendored Brotli decoders" (https://github.com/NixOS/nixpkgs/issues/578375) to track that. I am not aware of other distros making such efforts.
Thus:
In NixOS, security updates are great and fast for leaf packages such as the kernel, but can be slow for many-dependents packages. Much of that can be mitigated by building things yourself, which is easy.
Hope this helps.
Edit: I see now which comment you mean:
https://www.reddit.com/r/openwrt/comments/1xka85h/comment/19...
The `-SNAPSHOT` build is the pre-release build. Can be downloaded e.g. on https://mirror-03.infra.openwrt.org/releases/25.12-SNAPSHOT/...
To more easily find your model you can use
https://firmware-selector.openwrt.org/?version=SNAPSHOT
which selects "SNAPSHOT" in the right dropdown box.
More details below:
Apparently for the Linux 6.12 series that OpenWRT uses it's only fixed in 6.12.113 (see https://news.ycombinator.com/item?id=50322061).
But the latest OpenWRT release has an older version, 6.12.112, as per https://openwrt.org/releases/25.12/changelog-25.12.6. And the release notes https://openwrt.org/releases/25.12/notes-25.12.6 do not mention CVE-2026-98432.
I checked OpenWRT git (https://git.openwrt.org/openwrt/openwrt/log/?h=openwrt-25.12) and the commit "kernel: bump 6.12 to 6.12.113" is only 40 hours old, and NOT released in an OpenWRT release: https://git.openwrt.org/openwrt/openwrt/commit/?h=openwrt-25...
If yes, that's exactly what the users in the linked bug report are asking Signal to add to be able to fix this problem themselves.
Which is all well; after all nobody is paying them to do it.
My complaint is that they + iOS simultaneously prevent able users from fixing it themselves, or paying somebody to fix it.
For example, my bug report that `+= 2` is broken has not been acknowledged (read?) by anyone for 3 years:
const size_t n = 13; // triggers the issue
#pragma omp parallel for
for (uint32_t i = 0; i < n; i += 2) { // counts PAST 13!
https://github.com/llvm/llvm-project/issues/70687https://github.com/signalapp/Signal-iOS/issues/5813
Interestingly here, the sqlite DB would be trivially fixable, and messages restorable, with the `sqlite3` CLI.
But there's no way to get at that sqlite DB file. Even if you change Signal's code to add a feature to export the DB, it apparently cannot see your DB, because iOS sandboxes that so that it is only visible to Signal builds signed with the Signal developers' keys.
So that means your messages are all there, on your device, running open-source software, and yet you cannot get them.
This cannot have been the intention of Signal being Free Software. Where is "change it to make it do what you wish (freedom 1)"?
(I do not use iOS myself but have friends suffering this issue. Everybody involved is programmers and yet we seem to be able to do nothing about it.)
So it seems that even though the messages are on the user's device, it really is the Signal developers who "own" that data, and have the exclusive and ultimate control over it.
Makes me wonder:
Does this mean users suffering this need to GDPR-request their data out from Signal?
Yet https://linear.app/Homepage doesn't scroll without jank on mobile.
Copyable vs Non-Copyable passkeys
Transferable vs Non-Transferable passkeys
Hardware-Backed vs Software-Backed passkeys
User-Present vs Non-User-Present passkeys
User-Verified vs Non-User-Verified passkeys
Attested vs Non-Attested passkeys
They forgot Roaming vs Platform passkeys
(roughly: movable vs device-bound).This is what e.g. PayPal uses to prevent you from using your Yubikey as a passkey, while it works perfectly as a passkey on other providers (e.g. Wise bank)
It's checkable in the browser with e.g.: `await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()`
What makes you bet that?
As far as I know, the kernel doesn't have any official CI. People test as they feel like it. Some people/companies build some CI initiatives, others don't use them.
https://lwn.net/Articles/972713/
Also the kernel has > 10000 Kconfig options. Somebody told me that 2^64 is a lot, and that 2^10000 is a lot more.
There are lots of cases of "we wrote our own X, here's how it works", but rarely the concrete internal knowledge shared about what existing Xs can't do and why.
When the motivation stops at "look, the naive thing wouldn't work" even before the "normal" thing everybody does (fetch), it leaves many open questions to which you probably have an answer already.
> password doesn't show up you know there's a problem
Here is your contradiction.
The normal person will just assume that some tech isn't working today again.
A key point of passkeys seems to be that it guarantees to the site owner that the user cannot be phished, without having to make assumptions on whether the user is tech-stupid.
As the article explains, "over 600 PB" = 25M code checkouts * 25 GB "compressed working copy".
So "fetched naively" here means doing a full `git clone` on every need for `git checkout`, which of course nobody should do, nor does that refer to "code that needs changing daily".
So probably its RSS usage is just mostly its own executable code?
If anybody can create any software anytime, everybody gets a lot of the Four Freedoms of Free Software (change it to make it do what you wish, distribute your modified version, etc), without even "having the source".
And all the programmers constantly feeding their new code into training is the contorted version of GPL'ing it.
Anyway, the website seems to be fixed now, nice!
If you can boostrap one version of stagex (so that its mold is trustworthy), I don't see why you can't use that to build another version of stagex.
As you say, you can rely on the cached binary because nothing in the old version's supply chain would change; it is pinned, and as long as you can build that, everything is fine.
https://delaybahn.com/en/?fromId=A%3D1%40O%3DK%C3%B6ln+Hbf%4...
Click the "+30 min (28/30 days)" tags to see the delays of the last month.
I also find Haskell's concurrency in practice much easier to reason about than Go's, let me do a pitch:
In Haskell you can just fork a thread and block till it's done. Threaded, "async" logic just looks like blocking serial code (but isn't blocking). I feel like in typical channel-based Go code I have to jump and scroll a lot in the code because of all the message-passing instead of block-scoped "blocking-style" variable use, and that this makes it hard to conclude whether the whole thing terminates or deadlocks.
In Haskell, channels are considered low-level concurrency primitives you should only use when you have no clean high-level primitives for it. This is because they are not "structured" concurrency: When you send something into a channel, it is gone out of your scope, and you now need to track in your brain where it is, and who should consume that thing in the right way ("message-passing").
For example, in Stolon, a high-availability Postgres orchestrator written in Go (https://github.com/sorintlab/stolon), I found the logic for failover with multiple channels and various timeouts very difficult to reason about when investigating failover bugs. I'm pretty sure that would read much easier in Haskell (see below how).
In Haskell, you can start 2, or N, things in parallel, and easily wait till they are done. You can invoke parallel `map` easily.
results <- mapConcurrently f mylist
If f throws on any element, the whole map throws, and other threads get cancelled automatically as expected.You can get bounded, steaming parallelism, easily.
You can set time limits to function calls writing
timeout 1000 (myIoFunction ...)
You can cancel any thread or computation, at any time. The same timeout function can cancel blocking IO operations, such as reading from the terminal or sockets, without having pass around `Context` objects like in Go (which, if you forget it, just makes things hang or deadlock).You wrap the 2 words "timeout 1000" around your function and done.
Concurrency _composes_ in Haskell. You can write
res :: Maybe (Maybe a) < timeout a (timeout b (myIoFunction ...))
and the returned type tells you cleanly at which level the cancellation occured (no mixing into the same `error` type.You can build trees of parallel operations that live and die together.
And there are no data races (because mutability is a very explicit thing), and I'm not even mentioning STM here (which allows you to do database-style transactions across variables) because that's already pointed out in another post.
As a composed example, in Haskell you can write:
timeout 1000 (race (downloadUrl ...) (forever (putStrLn "Still loading ...")))
and that will do exactly what you think it should, with correct Ctrl+C cancellability, and good developer ergonomics.If you enjoy concurrency, give Haskell a shot!
I believe Go didn't originally have it, and added it in 2020, 14 years after Haskell.
> integer literals become i32, float literals become f32
Don't use the shitty small sizes that have introduced countless bugs over the last decades, as a language default.
Especially if you care about correctness.
i32 is all over the examples.
Use 64 bits, like Python and Haskell; even JavaScript and thus TypeScript got floats right defaulting to f64.
Killer feature!
> from the past three years [..] the latest I’ve seen were Opus-4.6 and GPT-5.5 struggle a lot with standard GHC Haskell
If your experience is from years ago, I totally get that. For my standards, LLMs were pretty bad before 2026.
I haven't tried any serious LLM Haskell before 2026-02, because it was just not a timesaver.
I had good experiences with Opus-4.6 already on Haskell, such as it having detail knowledge on async exceptions, allowing it to immediately pinpoint difficult bugs that me and other experts missed, e.g. https://github.com/snoyberg/conduit/pull/530
But most of my experience is from Opus >= 4.8. I found it excellent at writing difficult TemplateHaskell and Generics implementations, such as oneshotting Postgres JsonPath queries derived from lens-like field accessors on Haskell types.
Note it's still not great at writing general high-quality "engineering" stuff, e.g. Opus 5.0 writes functions that refer to things out of their scope, such as:
requireFooOr400 :: MyMonad m => Maybe Foo -> m Foo
requireFooOr400 x = case x of
Nothing -> throwHttp400 "Cannot perform [very specific action from the caller]: the inputs have no foo"
Just foo -> return foo
However, that's not a lack of Haskell understanding, and it does that for all languages, e.g. in Python it keeps writing implementation details into API docstrings instead of function body comments.Such as these non-frontend devs?
Does "Square ring" really look jerky/retro?