<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: unscaled</title><link>https://news.ycombinator.com/user?id=unscaled</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Sat, 22 Aug 2026 08:20:23 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=unscaled" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by unscaled in "Japan tried to build an operating system for the world, the US intervened"]]></title><description><![CDATA[
<p>You can mix Japanese and Chinese with modern document authoring standards or with HTML, but the fact is that most people are too lazy to do that. It's a pet peeve of mine when a document gets displayed with a Japanese font but then falls back to another Chinese font when it encounters characters that are missing in the Japanese font. Even when the fonts look the same (or when you're using a unified CJK font like Noto), things will still look bad if the language is not specified, since some characters are written different in each language (or even different variants of Chinese), but still got unified[1].<p>I laud what TRON tried to do, but I don't think they had it right. They made the encoding too complex (especially for the 1990s) while Unicode offered a single Basic Multilingual Plane. Unicode quickly got complex too (mostly due to the mistake of adopting UCS2 and then repurposing that as UTF16 and adding surrogates, and later getting a little bit over the top with combining emojis), 
but TRON was complex in other ways. If you mixed both Chinese and Japanese in a single documents, you had a multiple encodings to care about and control characters to switch between them. Suddenly, the character encoding is not stateless anymore. You can say the same about Unicode, but the statefulness of UTF-8 or UTF-16 is local and easily recoverable. Same goes for the statefulness  combining diacritics, and bidirectional markers (which are rarely used) only affect the display. TRON code plane switches, as far as I understand, mean that even a simple text search or regex search would stop working and need to be completely redesigned, since it now has to be aware of which language we're reading right now! That's a big break, as you say.<p>> It also had a lot more characters. Unicode dropped some of the older or rare characters, meaning some people can't write their last name with the correct character on a computer with Unicode.<p>Only if they're very old and born before or during the war or its not their legal name. The Japanese government restricts the Kanji that can be used in names to Jōyō kanji (regular use kanji) and Jinmeiyō kanji (personal name kanji). Together they add up to roughly 3000 kanji. The list was back in 1991 when Unicode 1.0 was released, but it did include all of them, and many more, as did previous Japanese standards that predated TRON like JIS X 0208. I feel like the "people can't write their name" was always a bit of cope. Japan is still the country of "the nail that sticks out gets hammered". If your name falls outside of the legally allowed list of Kanji, you'll suffer even if you're running BTRON.<p>[1] <a href="https://en.wikipedia.org/wiki/Han_unification#Examples_of_language-dependent_glyphs" rel="nofollow">https://en.wikipedia.org/wiki/Han_unification#Examples_of_la...</a></p>
]]></description><pubDate>Fri, 21 Aug 2026 11:16:05 +0000</pubDate><link>https://news.ycombinator.com/item?id=49386448</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49386448</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49386448</guid></item><item><title><![CDATA[New comment by unscaled in "Japan tried to build an operating system for the world, the US intervened"]]></title><description><![CDATA[
<p>I don't know how much the USTR campaign against TRON affected the success of BTRON, but I feel like we should be careful about this explanation. This is a classic example of American exceptionalism, but it seems like the USTR mandate just created a certain amount of FUD around TRON at best. You can see that it targets both BTRON (The desktop version TRON) and CTRON (the telco version of TRON), but unlike BTRON, CTRON did see real adoption and even dominance in the 1990s.<p>I think the main reasons behind BTRON failure like in the domestic market. I really don't know much about this period but here is my understanding. BTRON was  never an OS, but rather a specification, a set of standards for how BTRON-compatible operating systems should behave. This is quite similar to POSIX, but the standard covered significantly more than POSIX (e.g. HMI guidelines and character encoding) and the BTRON standard came _before_ the implementations. But just like POSIX, there was no guaranteed ABI compatibility. And to make things worse, every implementation had to be rewritten from scratch, while most Unix distributions before GNU traced their code all the way back to AT&T Unix.<p>The other issue is that with BTRON1, the OS implementation seem to have been expected to be developed by the hardware vendor - they were not envisioned as highly portable operating systems yet.<p>The different OSs were supposed to be developed by OEM vendors and interated directly into their hardware (especially with BTRON1). From what I could find, only 3 vendors have signed up for BTRON: Matsushita (Panasonic), Toshiba and OKI[1]. As far as I can tell, out of the three, only Panasonic ended up releasing BTRON-based computers. Panasonic went quite heavy on TRON and released multiple BTRON products, but Panasonic was a minor player in the home PC market in 1990[2].<p>Another small company that picked up BTRON was Personal Media. They released a sizable variety of BTRON-based hardware during the years and eventually started releasing it as a software package. In fact, they're still active today, rleasing it as chokanji, running inside a VM on Windows[3]. They basically took BTRONs impressive Kanji support and pivoted to an IME allowing inputting Kanji characters outside of Unicode.<p>The names that are missing from this story are all the big players in the PC industry in Japan in the 1990s. It's obvious why IBM Japan wasn't onboard, but NEC had its own monopoly to protect and Fujitsu and EPSON were clearly not interested[4]. CTRON, on the other hand, was picked up by NTT, which is probably the only company that mattered in Japanese telecommunications back in the early 1990s. BTRON had a window of opportunity in 1990, since Japan (or the rest of the world for that matter) did not have a dominant GUI platform yet. But in a market where the OS came with the hardware, lackluster vendor supported kinda sealed the deal.<p>[1] <a href="https://qiita.com/ko1nksm/items/243865903ae48c2c2c29" rel="nofollow">https://qiita.com/ko1nksm/items/243865903ae48c2c2c29</a><p>[2] AFAIK it was heavily dominated by NEC, with the smaller players bein Toshiba, Fujitsu and Epson. In 1990, when the first BTRON implementations were released, the dominant standard was PC-98, which was developed by NEC, with Toshiba and Epson making PC-98 clones. Even though all these computers were running x86 and usually ran on MS-DOS, they were NOT compatible with IBM PCs. This is mostly due to IBM PC not having enough RAM to display Kanji, so the which Japanese PC manufacturers in the 1980s solved with custom Kanji ROM chips. Getting Kanji support throughout the stack also meant heavily modifying MS-DOS and producing a different software stack that is tied to the custom hardware.<p>1990 is also the year that both DOS/V (a localized version of DOS that had built-in Kanji support) and Windows 3.0 were released, and both of them eventually lead to the death of domestic Japanese PC standards, since they could sufficiently support Kanji in software. 286 and 386 based PCs with extended memory were also powerful enough now to support Kanji in software, and DOS/V and Windows provided a standard application runtime environment for that. But this eventual standardization took time and back in 1990, PC-98 dominated the home market, while IBM managed to get some corporate market share with its PS/55 (an IBM PC variant with a custom display adapter with its own Kanji ROM).<p>[3] <a href="https://www.chokanji.com/" rel="nofollow">https://www.chokanji.com/</a><p>[4] OP happily mentions NEC, Hitachi, Mitsubishi and Fujitsu, but it fails to mention that they joined <i>other</i> TRON initiatives (ITRON, CTRON and The TRON chip) and explicitly declined to join BTRON.</p>
]]></description><pubDate>Fri, 21 Aug 2026 10:46:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=49386242</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49386242</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49386242</guid></item><item><title><![CDATA[New comment by unscaled in "The August 17 outage"]]></title><description><![CDATA[
<p>In highly distributed microservice architecture, there's almost never a single upstream. In some cases you may have a couple of customer-facing entry-points (a global API gateway, and a couple of BFFs), but these are not the only paths that need to be protected.<p>There are client-side retries (which have broken GitHub in this case) and server-side initiated API calls between microservices that don't pass through any of your ingresses (e.g. triggered by an ETL pipeline, or a scheduled job).<p>With a complex architecture you can't just slap a circuit breaker on a couple of ingresses and call it a day. Don't get me wrong, putting them there does go a long way, but you won't be covering all your bases.</p>
]]></description><pubDate>Fri, 21 Aug 2026 02:42:22 +0000</pubDate><link>https://news.ycombinator.com/item?id=49383069</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49383069</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49383069</guid></item><item><title><![CDATA[New comment by unscaled in "The August 17 outage"]]></title><description><![CDATA[
<p>> To handle this correctly you need your RPC framework to accurately communicate retryable vs non-retryable failures to clients.<p>Even this is not enough, since you cannot always reliably know whether service B is dead or suffers an intermittent issue that can be safely retried just from looking at a single failure.<p>The classic solution, in the monolith/few-services world would be a circuit breaker. High failure rates on any service trigger a circuit breaker in the services calling it, and they'll wait for a cooldown period before trying again.<p>When you move to a massive microservice architecture with hundreds or thousands of microservices, setting up circuit breakers manually becomes very hard to track and do reliably. Service meshes like Istio make this slightly easier, but they still don't let you verify that all possible paths have circuit breakers and that retries are not excessive etc.</p>
]]></description><pubDate>Fri, 21 Aug 2026 02:34:59 +0000</pubDate><link>https://news.ycombinator.com/item?id=49383009</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49383009</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49383009</guid></item><item><title><![CDATA[New comment by unscaled in "The August 17 outage"]]></title><description><![CDATA[
<p>I think the "happy path" might be a slightly wrong classification in GP, since the post is in reply to a retry-storm issue and explicitly talks about retry storms and thundering herds.<p>I've seen many cases where engineers optimize the sad path, but pessimize the wretched path. Or in less flowery language, they cut the occurrence rate of common non-critical failures, but by doing that they introduce code that can make rare failures much worse.<p>The cases I've seen generally boil down to naive retry logic or poorly tested and poorly maintained fallback paths (such as killswitches that break their environment[1], graceful degradation turned graceless, dormant feature flags that get reactivated).<p>The case you see with a retry storm here is the most classic one and the one that annoys me the most. I've seen engineers adding aggressive retries even into places where the impact is minor (you could show an error and let the user manually retry instead). Retries that improve user experience can be great if done correctly, but I've never seen the authors of such pull request addressing the risk and mitigation techniques for retry storm or retry amplification.<p>I've seen cases which had:<p>1. Retries on the client side (browser or mobile app).
2. Retries on the BFF.
3. Retries on Microservice A used by the BFF.
4. Retries on Microservice B used by Microservice A.
5. Retries on Critical Service C used by Microservice B.<p>Most of these retries had very short timeouts (e.g. 100ms), in order to keep latency SLOs during normal operations (not a good idea on retries). Every time QA saw a layer without retries, that would be a bug, and adding retries is easy, so we'd get a new retry without much thought. But the first time Critical Service C became overloaded, Microservice B started timing out a couple of times and retrying. This was too much too much for Microservice A that had a short timeout that couldn't hold the 3 retries done by Microservice B, so it making doing its own retries, all of them dropped in the middle of the way. Eventually you'll get a full-blown retry storm where every request from the client side got amplified with 3^5 retries, easily bringing down Critical Service C.<p>We'd usually introduce a circuit breaker for the particular path that caused the issue, but a variation of this kept happening several times because designing safe retries across a vast collection of microservices takes a lot of effort, and it's always easier to just add a quick-and-dirty retry at any point where you think you might need one and call it a day.<p>A proper solution (which I've never seen implemented) would be an mandating a corporate-wide inventory of retry-paths, and monitoring it for any path that is at risk of triggering a retry storm, or adding mandatory headers that cross microservices and track the amount of retries done up the chain and the time spent in total waiting for previous retries. You could have a budget for both and automatically stop performing more retries. Both solution require extra effort and a large degree of coordination.<p>[1] This was the CloudFlare issue mentioned in this thread <a href="https://blog.cloudflare.com/5-december-2025-outage/" rel="nofollow">https://blog.cloudflare.com/5-december-2025-outage/</a></p>
]]></description><pubDate>Fri, 21 Aug 2026 02:23:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=49382946</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49382946</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49382946</guid></item><item><title><![CDATA[New comment by unscaled in "Go is an ideal language for AI-assisted software engineering"]]></title><description><![CDATA[
<p>That's my take. The arguments for Go over Rust used to be:<p>- Better concurrency story<p>- Native cross-compilation of static binaries (great for CLIs)<p>- Easier to learn, easier to teach<p>- Opinionated: You don't have to enforce a single style everywhere<p>Concurrency died out as an argument when Rust async/await got better. Sure, it has "function colors" and that matters for weird purists who care very much about typing a single "await" in their code, but don't care at all about typing "foo, err := bla(); if err != nil { return err }" all over the place. But it doesn't matter in practice, and tokio has far better concurrency tools: there ares separate channel for mpsc, oneshot, broadcast and watch scenarios, there Streams, JoinSets and a select! macro that can operate more than just channels.<p>The static compilation argument also died pretty early on when the Rust musl target became more mature. It's still slightly easier to get cross-compilation started with Go, but now that you we have LLMs we wouldn't care.<p>The learning curve argument is dead. It used to be harder to hire or train Rust programmers and that was a real pain. But LLMs don't care. The same goes for the "Go is built for software engineering" argument, which is a euphemism "Go is our way or the highway level of opinionated". LLMs do not need an opinionated language as much as humans do. If you want all code to follow an arbitrary standard, just ask your LLM to set up one. Engineering teams used to spend years bikeshedding things like brace styles and spaces vs. tabs and Go went ahead stole that opportunity from them. But this is no longer needed.</p>
]]></description><pubDate>Wed, 12 Aug 2026 03:33:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=49267565</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49267565</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49267565</guid></item><item><title><![CDATA[New comment by unscaled in ""Clean" Code, Horrible Performance (2023)"]]></title><description><![CDATA[
<p>I don't think it was true even in 2023.<p>This sounds like tackling the problems of C++ in the early 2000s.<p>1. Casey Muratori also that DRY shouldn't doesn't have to result in non-performant code.<p>2. Smaller functions, functions that do one-thing: Modern compiler can inline those. There are some edge cases where inlining may make less efficient use of states and loops but I don't think that's a main problem nowadays. I also wouldn't say the extreme version of this idea (very small functions) is still popular. The strongest proponent of this was Uncle Bob, and the last time I've heard him speak about code, he said he now lets the LLM write everything and he only reviews the module hierarchy and maybe the modules' public interfaces.<p>3. Polymorphism instead of ifs and switches was a big fad in the late 1990s until the late 2000s and had some holdouts in the 2010s. It was only ever popular in the Enterprise Java and C++ world (and maybe in Enterprise Smalltalk, never hard). Overuse of runtime polymorphism widely considered bad form in newer static languages like Go and Rust and in most dynamic languages there was always a tacit understanding of "use mostly conditions, add polymorphism if you need extensibility".<p>In functional languages (or languages heavily influenced by functional programming like Rust, Swift and Kotlin[1]), the classic approach for the type of scenario in this example is to use a sum type, and run a safe exhaustive match/switch on all the variants.<p>4. Hiding internals: The sum type example is telling of modern best-practices. Sum type fields are generally made public. Some languages (e.g. Rust and most pure functional languages) do not support private fields in sum types at all! Other languages (e.g. Kotlin)
 but immutable, so it's easy to maintain invariants without hiding information. Sometimes we do want to hide the type details and wrap it with public-facing type (this is a common pattern with internal error enums in Rust for example). Even in this case, there is no impact since we do not use runtime polymorphism or indirection (that would be Box<T> in Rust).<p>Due to compiler optimizations, hiding internals has marginal performance cost (if any) unless you require runtime polymorphism to achieve it. But why should you?<p>I feel like the performance costs lamented in this article mostly have to do with runtime polymorphism in static languages. And I fully agree here: runtime polymorphism is something that should be avoided when you don't need it[2]. But that's the thing: if you're looking at modern static language codebases, runtime polymorphism is not as hyped as it used to be in the past. Some languages still require heavy use of runtime polymorphism (Go is a good example of this), but other languages more often rely on static polymorphism (Rust) or compile time duck-typing (Zig and you could argue C++ template meta-programming used to do that, albeit quite awkwardly).<p>Even with all the issues you get with polymorphism, I don't think it's the main cause of slow application performance. It be very much the culprit in tight loops inside games, but if you look at the performance issues plaguing everyday apps, I think the two major culprits are endless layers of abstraction (the most quintessential example is basically every sluggish Electron app out there) and blocking the user on slow actions (like network loads).<p>---<p>[1] Even Java had sealed record types for a while now, and I'm sure will see Enterprise frameworks encouraging them in 20 years, when the rest of the world has moved on to spacefaring super-intelligent LLMs. But Enterprise frameworks also don't encourage you to write DRY code or keep your functions short.<p>[2] But do keep in mind that in Java it could be almost zero-cost in many cases. The JIT will monomorphize or bimorphize your classes if you always use the same class at the same callsite. The pointer indirection is not an extra cost, since every non-primitive that doesn't undergo Scalar Replacement[3] lives on the heap, and has a pointer.<p>[3] <a href="https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacement/" rel="nofollow">https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacemen...</a></p>
]]></description><pubDate>Tue, 04 Aug 2026 14:58:06 +0000</pubDate><link>https://news.ycombinator.com/item?id=49169906</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49169906</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49169906</guid></item><item><title><![CDATA[New comment by unscaled in "Our position on open-weights models"]]></title><description><![CDATA[
<p>For this testing to be really effective at stopping "dangerous and misaligned" models from leaking out, you need a mechanism for banning failed models that prevent them from being released in the first place, not just prevent US companies from using them.<p>The only way to stop this from happening is blocking the model's release at the first place. Which requires China agreeing to the same framework. Dario says exactly the same thing himself.<p>So if he's being truthful here, he's not advocating for the type of ban people are talking about (usage ban). This kind of ban would be helpful to Anthropic's business in the short term, but it won't prevent Chinese models from improving, and it won't prevent them from getting money selling to other countries.<p>He <i>is</i> openly advocating for an international effort to enforce tests on public models, but I think this is highly unlikely in the current climate. Even if both the US and China agree that public models should be prevented from being used in designing bioweapons, they need to agree on a test and enforcement framework and that requires a lot of negotiation and trust. I don't see this as likely in the near future.</p>
]]></description><pubDate>Tue, 28 Jul 2026 02:46:01 +0000</pubDate><link>https://news.ycombinator.com/item?id=49078645</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49078645</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49078645</guid></item><item><title><![CDATA[New comment by unscaled in "Kill The Cookie Banner"]]></title><description><![CDATA[
<p>The law is airtight. Acceptance must be informed and freely given (this includes forcing through dark patterns and annoying banners that force you not to read), and withdrawal should be as simple as acceptance.<p>GDPR article 7 and its various recital already include that. GDPR wisely doesn't get into technical details like "cookie banners" anywhere, but various national agencies did set guidance and it's usually quite explicit: Rejection must be as simple as acceptance and reject buttons or link must be as prominent as the accept buttons and links.<p>For example, CNIL, the French data privacy authority, clearly says[1]:<p>"The CNIL has received complaints about dark patterns on cookie consent banners encouraging data subjects to accept cookies.<p>As a reminder, with certain exceptions, cookies can only be used with the consent of data subjects. Moreover, rejecting cookies should be just as easy as accepting them."<p>And gives examples of dark patterns such as different button sizes, multiple accept buttons, hidden reject buttons, etc.<p>The law and specific guidance is pretty unambiguous. This purely an enforcement problem. The regulatory bodies do not have the resources to go and chase most individual companies, and the non-profit NGOs that go after the violators apparently don't have the budget to make enough impact and scare companies into
compliance.<p>[1] <a href="https://www.cnil.fr/en/dark-patterns-cookie-banners-cnil-issues-formal-notice-website-publishers" rel="nofollow">https://www.cnil.fr/en/dark-patterns-cookie-banners-cnil-iss...</a></p>
]]></description><pubDate>Mon, 27 Jul 2026 04:48:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=49065292</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49065292</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49065292</guid></item><item><title><![CDATA[New comment by unscaled in "Kill The Cookie Banner"]]></title><description><![CDATA[
<p>Despite this being called a "cookie banner", this is not _just_ about cookie. When you click "Accept all" you are giving your consent to any form of tracking and information sharing mentioned in the details. The site you visit may share everything they know about you with any third party they mentioned. They can even use fingerprinting (if you've agreed to it) to keep tracking you after you've deleted the cookies.</p>
]]></description><pubDate>Mon, 27 Jul 2026 04:30:59 +0000</pubDate><link>https://news.ycombinator.com/item?id=49065208</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49065208</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49065208</guid></item><item><title><![CDATA[New comment by unscaled in "Passkeys were invented by engineers with zero understanding of consumer brain"]]></title><description><![CDATA[
<p>It doesn't even have to be something as bare-bones as pass. You can have a full-fledged password manager that is open-source and local-first. KeepassXC (and the OG Keepass) were always OSS and local-first. The original version of Keepass 1.0 for Windows was released long before Lastpass or 1Password[1], so we had an open-source local-first password manager before we had commercial cloud-based managers.<p>[1] To be more accurate, although it was always proprietary, 1Password was also local-only at first, with syncing only supported by putting it on something like Dropbox. They only added native cloud syncing later and eventually made it cloud-first.</p>
]]></description><pubDate>Wed, 22 Jul 2026 19:45:16 +0000</pubDate><link>https://news.ycombinator.com/item?id=49012379</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49012379</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49012379</guid></item><item><title><![CDATA[New comment by unscaled in "Passkeys were invented by engineers with zero understanding of consumer brain"]]></title><description><![CDATA[
<p>"supposed" is doing a lot of heavy-lifting here. According to who? The FIDO2 or Webauthn standards? Or in a perfect world?<p>FIDO 1.0 started as two different standards: UAF and U2F. U2F was for USB keys used as second factors (so almost always stored in a TPM-like chip and device-bound, but not provided by your platform and there could be multiple of them). UAF were either provided by your platform or by any software and there was no requirement for them to be stored in TPM. Back in the day, very few platform had any FIDO support built-in, so in practice UAF was always done in software (usually based on whatever biometrics/TPM the hardware provided).<p>So competing options were the default for early FIDO, getting a default platform option is something that came later.</p>
]]></description><pubDate>Wed, 22 Jul 2026 19:35:25 +0000</pubDate><link>https://news.ycombinator.com/item?id=49012248</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49012248</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49012248</guid></item><item><title><![CDATA[New comment by unscaled in "Passkeys were invented by engineers with zero understanding of consumer brain"]]></title><description><![CDATA[
<p>Passkeys is basically a brand name for "discoverable credentials" (a Webauthn term). They do a little more than that technically, but in practice their purpose is what you said. Replace passwords. Or more accurately usernames and password pairs. This is in contrast from 2FA, but even before Apple started marketing Passkeys the FIDO standard supported the concept of Passwordless authentication, alongside 2FA.<p>Passkeys came together with multi-device syncing when Apple introduced them and IIRC it was pushed as their killer feature by Apple back then, but passkeys can also be completely device-bound. The marketing around this was all quite confusing, but it's a bit too late to fix now.<p>What we got, as far as the average consumer should be concerned, is that "passkey" is any authentication mechanism (not the actual credential) that can replace a password. And it's still confusing.</p>
]]></description><pubDate>Wed, 22 Jul 2026 19:27:46 +0000</pubDate><link>https://news.ycombinator.com/item?id=49012138</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49012138</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49012138</guid></item><item><title><![CDATA[New comment by unscaled in "Passkeys were invented by engineers with zero understanding of consumer brain"]]></title><description><![CDATA[
<p>The FIDO set of standards (UAF, U2F which predated passwords and passkeys) haven't even started as enterprise standards. There are multiple origins for what became FIDO, but the main ones I know are:<p>1. PayPal was looking for a physical authentication solution for their users, Michael Barrett was their CISO at that point and he became the president of FIDO.<p>2. Google developed Gnubby (which <i>was</i> internal, and therefore enterprise) and they wanted to push a similar authentication to their end-users, supported directly on Chrome. They wanted this to become a standards, so donated the underpinnings of the Gnubby technology which became FIDO U2F.<p>I might be wrong but at least these are the two parts I know.<p>And while the original FIDO could be called dual-use, Webauthn and especially Passkeys were developed to be first and foremost a customer-facing standard.<p>It doesn't mean they are not confusing, but they are clearly designed with end users in mind.</p>
]]></description><pubDate>Wed, 22 Jul 2026 19:10:40 +0000</pubDate><link>https://news.ycombinator.com/item?id=49011929</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=49011929</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49011929</guid></item><item><title><![CDATA[New comment by unscaled in "Stop Using JWTs"]]></title><description><![CDATA[
<p>For what? For just authenticating a client application to a server without getting access to any user data? By all means. You usually don't need the client credentials in OAuth 2.0 if you don't want to use it.<p>But if you want access to user information, you can't just give access to an app that has a shared secret key to a all user data for every single users in the planet. You need to authenticate the user somehow, and sharing the user's password directly with the app is not a good idea for many reasons.<p>Even if you trust the app to be "written without any bugs", the moment you allow the password grant in OAuth, your service cannot use CAPTCHA, MFA or Passkeys efficiently. The password grant does not allow any of these, so this app that you've let through becomes the weakest link for all cybercrime groups that want to attack your service.</p>
]]></description><pubDate>Sun, 21 Jun 2026 13:14:24 +0000</pubDate><link>https://news.ycombinator.com/item?id=48618702</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=48618702</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48618702</guid></item><item><title><![CDATA[New comment by unscaled in "Stop Using JWTs"]]></title><description><![CDATA[
<p>PKCE, OAuth 2.0 for Native Apps and the Device Code flow are a thing. In practice all of these clients work so well with OAuth 2.0, that the implicit and resource owner password credential grants have been removed from OAuth 2.1 and are the latest OAuth 2.0 BCP forbids the password grant and strongly recommends against the implicit grant.</p>
]]></description><pubDate>Wed, 17 Jun 2026 14:21:31 +0000</pubDate><link>https://news.ycombinator.com/item?id=48570957</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=48570957</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48570957</guid></item><item><title><![CDATA[New comment by unscaled in "Stop Using JWTs"]]></title><description><![CDATA[
<p>I wish I was young. Did I explicitly said TLS __1.3__ or did I not?<p>A lot of effort was put into making TLS 1.3 a stronger, less agile and more misuse-resistant standard than its previous iterations. And that effort worked.</p>
]]></description><pubDate>Wed, 17 Jun 2026 14:16:36 +0000</pubDate><link>https://news.ycombinator.com/item?id=48570896</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=48570896</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48570896</guid></item><item><title><![CDATA[New comment by unscaled in "Stop Using JWTs"]]></title><description><![CDATA[
<p>True. But XSS stealing your token (which is always possible with localStorage) is still worse than XSS using your token. It's the principle of least privilege all over again.</p>
]]></description><pubDate>Wed, 17 Jun 2026 09:08:37 +0000</pubDate><link>https://news.ycombinator.com/item?id=48567739</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=48567739</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48567739</guid></item><item><title><![CDATA[New comment by unscaled in "Stop Using JWTs"]]></title><description><![CDATA[
<p>The main reason I don't like the id token is that I've seen way too many instances of the ID token being used as a trusted identity assertion sent across multiple services or to third parties. This is very dangerous, since ID tokens tend to have longish expiry (several hours), are not revocable, and generally do not carry any concept of authorization (e.g. restricted scope).<p>It would have been better if instead of implementing ID tokens, OIDC <i>only</i> supported the authorization code flow and returned a JSON payload of claims (which nobody would incorrectly assume to be trustworthy).</p>
]]></description><pubDate>Wed, 17 Jun 2026 09:07:05 +0000</pubDate><link>https://news.ycombinator.com/item?id=48567727</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=48567727</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48567727</guid></item><item><title><![CDATA[New comment by unscaled in "Stop Using JWTs"]]></title><description><![CDATA[
<p>The OP was talking about sessions (which include session cookies and API tokens). I'd argue these use cases are far more common for the average programmer than tokens and signatures that are used for federation, but I'll bite the bullet here:<p>JWT is a serviceable solution for service trust and federation. This use case often just requires a very-short-term token, so lack of revocation support is not an issue. Replay attacks are still an issue, but they can also be prevented with single-use nonces that are included in the token claims.<p>The OP's take (and my take as well) is that JWT is rarely the BEST solution for this use case. You kinda have to use it if you need to implement a standard that mandates JWT such as OpenID Connect. But OpenID Connect is a great example for a place where JWT was used, but was never really necessary. If you do use the authorization code flow securely (on the server side, with a strong client secret and proper CSRF protection) you don't need the ID token. In fact, you don't need to use any cryptography at all! Just like random session IDs, you've got a stateful solution that works reliably without any cryptography.<p>If you cannot do a series of authenticated network requests between HTTPS endpoints to verify trust, then a signed payload could be useful, but you've got better standards than JWS/JWT for that. That's all.</p>
]]></description><pubDate>Wed, 17 Jun 2026 09:02:38 +0000</pubDate><link>https://news.ycombinator.com/item?id=48567688</link><dc:creator>unscaled</dc:creator><comments>https://news.ycombinator.com/item?id=48567688</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48567688</guid></item></channel></rss>