I recently released rawzip 0.5, a zip archive file parser that focuses on minimalism in terms of dependencies (there are none) and overhead. 
 Looking at benchmarks: rawzip has anywhere from 15x to 15000x less overhead than the next fastest zip library. 
 
 I’m using the overhead terminology deliberately. Most use cases should see compression dominate profiles. Most . 
…
Over 5 years ago I wrote about overhauling a JS parsing library by rewriting it in Rust and compiling to Wasm. 1 I smugly implied that this would go unnoticed by users: 
 
 By inlining as base64 we make the Wasm an implementation detail 
 
 This was the wrong mentality 5 years ago, and it’s the wrong mentality today. It took me a couple years to fix the recommendation 2 , but…
Arena allocators are having a moment in the Rust ecosystem. They’re powering the next generation of JavaScript tooling 1 , showing up in Reddit success stories 2 , and promising three key benefits: 
 
 Amortized allocations 
 Cache locality 
 Efficient drops 
 
 I’m working on a project that deserializes 200MB of binary data in the browser via Wasm, where…
Wasm-pack, the rustwasm working group, and other Wasm related tools were sunset and archived in July 2025 1 , after more than 5 years of being on life support. Thank you to all who made Wasm and Rust what it is today: a tech stack that continues to enthrall me. 
 Despite the years of ongoing maintenance issues, I and others continued to use wasm-pack as it’s recommended by the…
Web workers that load Wasm through an ES6 import with the help of bundler plugins can silently drop messages during startup. This happens because the top level await for Wasm’s asynchronous initialization blocks the worker’s message handler registration, creating a race condition that’s often invisible. 
 As an example, the web worker module below will drop messages until…
A light-bulb went off over my head when I wrote a loop that contained repetitive lookups with no conditional logic: 
 // pseudocode
 let data = [ 0 u32 ; 1024 ];
 let indices = [ 0 u16 ; 1024 * 1024 ];
 let output = [ 0 u32 ; 1024 * 1024 ];
 for i in 0 .. output.len() {
 output[i] = data[indices[i]];
 }
 That for-loop is the poster child for AVX2 gather instructions…
I didn’t understand the hype around Duckdb, until I was approached to query a set of proprietary-yet-close-to-json files I have totalling 300 GB uncompressed, 25 GB compressed. 
 For prior requests, I wrote a bespoke CLI program to process the files and spit out the statistics. It was finally time for the task: package the data in a format that allows one to make arbitrary queries. 
…
There are several options for how to structure a Bevy app for the web: 
 
 Run the Bevy app and canvas on the main thread 
 Run the Bevy app on the main thread but with an OffscreenCanvas 
 Run a Rust “window” on the main thread with the Bevy app and OffscreenCanvas in a web worker 
 Remove Rust from the main thread and run everything in a web worker 
 
 As…
Oftentimes the size of addressable space is the same size as the system architecture’s preferred unit of operation, also known as its word size . On the vast majority of consumer hardware and servers (both x86 and Arm), these will both be 64 bits. 
 However this is not the case with Webassembly (Wasm), which has 32 bits of addressable space 1 but a word size of 64 bits. 
 But wait,…
TLDR : In a real world benchmark, the default musl allocator caused a 7x slowdown compared to other allocators. I recommend all Rust projects immediately add the following lines to their application’s main.rs : 
 // Avoid musl's default allocator due to lackluster performance
 // https://nickb.dev/blog/default-musl-allocator-considered-harmful-to-performance
 #[cfg(target_env =…
pread is a little known POSIX API that allows one to issue file reads at an arbitrary offset in a thread-safe fashion, as it won’t mutate the file’s underlying cursor. 
 The Linux man-pages give us insight into pread’s usefulness along with its sibling, pwrite . 
 
 The pread() and pwrite() system calls are especially useful in multithreaded applications. They allow…
React server components. Streaming server side rendering. Edge compute. Web app architecture advancements are making classic SPAs appear long in the tooth. 
 Time to see what I’ve been missing, and try to keep up with the Joneses (negative connotation fully implied). 
 I might suffer from Perpetual Reengineering Syndrome as this is the umpteenth time a 100k LOC web app side project…
I’m moving more code into Cloudflare workers everyday as they are cheap, fast, and powerful. But it hasn’t been without struggle. 
 This is the story of one such struggle with a troublesome endpoint. 
 The endpoint in question verifies the OpenID authentication signature directly with Steam. In short, this code runs after the user authenticates with Steam, and when we receive a…
Did you know that the files originating from an file input don’t have all their data buffered into memory? Seems intuitive that this is how JS would work, otherwise web sites operating over files would be terribly memory inefficient. 
 Don’t let this efficient File deceive you. If you create one yourself, you’ll soon find that you need to buffer all data into memory. 
 To…
In an app that has S3 files and a Postgres database storing file metadata, we might have a DELETE route that looks something like: 
 
 Select file from db, and if it does not exist throw a 404. 
 If the file’s owner isn’t our session’s user, check the db if the session’s user is an admin 
 Delete file from the db 
 Delete file from S3 
 
 The…
I came across some high usage under my Vercel account. 
 
 
 
 
 
 Vercel usage donut charts. Cropped for brevity 
 
 

 What is “Fast Origin Transfer”? The docs are vague , and whatever it is, seems like I’m about at my limit. 
 Vercel used to have straightforward pricing, but they recently updated their model . 
 
 Instead of…
Last month I found myself in the unenviable position of having just executed the most dangerous command ( dd ) on the boot drive of the NAS of my homelab. I was trying to wipe stale ZFS partition information from a data drive after it became briefly detached, but on reboot, the drive labels had been reassigned and I didn’t double check if I was wiping the correct drive. 
 I caught my…
Let’s write a function that takes in a file extension and returns a file type: 
 function fileType ( fileExtension : string ) {
 switch ( fileExtension ) {
 case '.mp4' : return 'video' ;
 // ...
 }
 }
 Our function assumes the file extension has a leading dot, but should it? 
 
 The Python standard library includes the dot in file extensions . 
 Rust…
An image sprite sheet is a collection of images combined into one, so that browsers don’t need to request each image separately. 
 How does one create a sprite sheet? 
 And how can we measure any potential benefit? 
 What problems can appear and how do we work around them? 
 
 This post features screenshots from pdx.tools . Game assets shown are from EU4 and are for…
Tanstack Query , (née React query for the purposes of this post) is a staple in async state and data fetching management. In addition to saving me from reimplementing similar caching mechanisms and fine grained updates, it was also the first library that solidified the concept of client vs server state, and how they are fundamentally different . Nothing is without tradeoffs, so I wanted to shed…
While React animation libraries have seductive landing pages and can be powerful, consider whether you truly need one. These libraries can enhance user experience, but sometimes the simplest solution is the best one. 
 Many animation needs are met with just CSS, so come along for a tour at ways one can add effects to their web application using this framework agnostic building block. 
…
Repeatedly adding orthogonal properties to a React component causes unwieldy bloat. Transitioning to a compound component will invert control and allow clients the flexibility they need. It comes at a cost, though. What are these costs, can we mitigate them, and what are alternative solutions? 
 Let’s build a motivating example of a component’s growth. Say we’re building an…
In his 2024 programming predictions video, Theo downplayed WebAssembly (Wasm) : 
 
 I don’t think [Wasm is] going anywhere next year. […] 
 When I see all of these new ways of building Rust based web applications, I cringe a tiny bit […], the size of the binaries are still pretty bad, the performance wins aren’t there, and the flexibility of a language like…
I felt clever. After spending a week developing an incremental lexer that would allow pdx.tools to deserialize decompressed saves at a constant memory usage, I was excited to integrate it. I had worked very hard to craft a serde deserializer that was optimized to pull from a lending, incremental lexer without the performance caveats seen in serde_json . 
 Writing a serde deserializer over a…
I was migrating a Next.js application ( pdx.tools ) from a self hosted instance to run serverless and edge functions over on Vercel . 
 One serverless endpoint accepts an uploaded EU4 save file, parses it via a microservice , uploads to S3, and sticks the parsed data in Postgres. Conceptually, the endpoint can be written: 
 export function POST ( req : Request ) {
 const bytes = new…
I was reading an article by PlanetScale , a hosted MySQL platform, called Why we chose NanoIDs for PlanetScale’s API . A decent enough article about Nano IDs and storing them in databases. 
 While there are no mistakes in the article, I think there is enough nuance omitted to warrant an addendum, otherwise others run the risk of misapplying the solution. 
 Here is the schema they used in…
The modern web is so complex, there came a time when updating to either the latest Ant Design 4 (antd) , or latest Next.js 13.4 version would cause PDX Tools to completely break with a nonsensical error. Something about a tooltip. After a couple hours searching the web and tinkering, no solution was in sight. A frustrating and humbling experience (or humiliating depending on how you look at it).…
Most should be in agreement that the following signature is in bad taste: 
 type MyObject = {
 price : number ;
 }
 Is the price in dollars, cents, or is it even some other currency? What’s protecting another developer (including the future self) from footguns? 
 // Mixing up dollars and cents
 const discountDollars = 2 ;
 const productCents = 10000 ;
 const…
There’s one endpoint in PDX Tools that has been a bit of a thorn in my side. It’s a critical, resource intensive endpoint that accesses proprietary embedded assets, but it’s executed very infrequently. For a site that recently broke a million monthly requests, only about 100 of these are to this endpoint. 
 The endpoint in question digests an uploaded compressed file and…
In pdx.tools , users have the option to upload their EU4 save files. Behind their .eu4 extension, these files are typically zips; zips that aren’t compressed very well. Extracting and recompressing the files nets around a 20% reduction in size. 
 As the person who pays for file storage, storing poorly compressed zips isn’t appetizing. Though I can understand why a game may prefer a…
When new browser APIs get announced or are implemented, like the recent announcement from the Chrome team about WebGPU, there is an inevitable push back: 
 
 [Is] this yet another information leak anti-feature that we need to disable? [source] 
 
 
 Nobody needs new fancy features, what people really need is more reliable fingerprinting [source] 
 
 
 The browser…
I, unironically, wrote a todo app: CycleList . 
 This was only after trying and failing to find an app or site where I could have a sequence of unscheduled tasks where completing a task would have it fall to the bottom of the list with an updated completed time. Tasks completed least recently then bubble up to the top, creating a sort of cycle. Hence the name, CycleList. 
 Use cases for…
Designing responsive web sites is a tale as old as CSS media queries, but with the proliferation of JS component libraries, like React, there is a trap that is starting to become a thorn in the side of rising popularity of server-side rendered (SSR) React. 
 The trap is that conditionally rendering above the fold components based on values from runtime-derived media queries, results in a…

 
 Interested in running the compression benchmarks yourself? It’s hosted at bench.nickb.dev 
 
 
 Lack of transparent compression 
 IndexedDB , the Cache API , and network requests will not transparently compress data, and I think this is a problem. 
 Testing was done on Chrome and behavior may vary by browser. 
 Let’s say we want a function to persist…
Web workers are crucial for responsive client side compute, but they have a notorious ergonomic hurdle, so large that I’ve previously debated whose responsibility it is to offload compute on the web: the library or the application developer. Not to spoil that article, but the decision is nuanced, essentially boiling down to: it is the library developer’s responsibility if it is the…
My apartment building recently switched ISPs. After they finished installing, all the sites I host on my home server were no longer accessible. Cue slight panicking, as I host everything from code to documents to analytics to a dozen other use cases. 
 I thought my dynamic DNS client, dness , would save the day, but it had already detected, propagated the new WAN IP, and the problem persisted.…

 Rust lacks a runtime, enabling small .wasm sizes because there is no extra bloat included like a garbage collector. You only pay (in code size) for the functions you actually use. 
 The Rust Wasm Book, “Why Rust and WebAssembly?” 
 
 We can see small Wasm sizes in action with a contrived example: 
 use wasm_bindgen::prelude::wasm_bindgen;
 
…
At PDX Tools , one has the option to upload an EU4 save file and the app will deduce what achievements were earned and how many ingame days have elapsed in the save. 
 With this information we can create a leaderboard for individual achievements. 
 Here’s the Postgres database schema to start us off, where we store the save id, the time it was uploaded, what achievements were…
The Rust crate for handling ZIP files, zip-rs is quite flexible. The zip crate is compiled with builtin features to support deflated data (among other compression algorithms). This makes it incredibly easy to hit the ground running for reading and writing zips. 
 We can disable these builtin features. This may sound undesirable, but in fact, it is my new favorite way to integrate zip…
With React continuing to march towards a strong streaming server side rendering story, the React working group published a guide for how dynamic CSS-in-JS libraries can adapt . At the end of the guide, it gives a lukewarm sendoff to dynamic CSS-in-JS libraries: 
 
 While this technique for generating CSS is popular today, we’ve found that it has a number of problems that we’d…
Banner octopus graphic from the Compose repo 
 Docker Compose has a nice feature where several Compose files can be seamlessly fashioned together and allow for configuration reuse across environments. There is, however, counterintuitive behavior that can lead one to accidentally overwrite remote container images. Since I lost several hours to this, I figured I’d write about it to sear…
For the uninitiated, JavaScript environments like node.js and the browser have a main thread that runs basically everything. Exhausting the main thread can have consequences, as MDN puts it : “long-running JavaScript functions can block the thread, leading to an unresponsive page and a bad user experience”. In the context of this article, responsiveness describes the UI’s ability…
Interested in seeing a library employing recommendations that will be laid out in this article? Check out jomini . The highwayhasher library takes this one step further by juggling an implementation that uses native code too! 
 Don’t like reading a life story on recipes? Skip to the next section. 
 With Wasm support in nearly all JS environments , I’ve become a large proponent…
A year and a half ago I wrote that My Bet on Rust had been Vindicated , as an incredible amount of code could be shared between the server and web client, and I could easily spin out C libraries and executables. No use case was out of reach. 
 But based on the title you know that the backend is no longer leveraging a Rust web server ( warp in this case). So what happened in the last year and a…
The AWS S3 Storage API is ubiquitous and has been picked up by other 3rd party storage vendors like Backblaze B2, Minio, Wasabi, Storj, and IDrive. This is excellent for developers and sysadmins as it facilitates integration testing and experimentation with cloud storage providers. There is an AWS SDK available for 10 languages so chances are you can use the official SDK and connect it to a…
Chrome, Firefox, and Node LTS have all stabilized the SIMD extension to Wasm in the last few months (Safari is lagging at the time of writing. See the updated roadmap for changes). Additionally, Rust has stabilized Wasm SIMD intrinsics recently too . All the pieces are set and now is the time to start authoring libraries that take advantage of the promised performance that SIMD can bring. 
…
The day I’ve known for a while has come: a drive in my ZFS array has become degraded. It’s my first drive failure in over four years , not bad. 
 Here’s the status report: 
 pool: tank
 state: DEGRADED
 status: One or more devices could not be used because the label is missing or
 invalid. Sufficient replicas exist for the pool to continue
 functioning in…
This example from a Rust issue does not compile: 
 struct X { a: u8 , b: u16 , c: u32 , d: i8 } 
 struct Y { a: u8 , b: u16 , c: u32 , d: i8 } 
 let x = X { a: 1 , b: 2 , c: 3 , d: 4 }; 
 let y = Y { a: 5 , .. x };
 The code does not compile as the struct update syntax, which is the ..x part from above, is contingent on the target struct being a subtype of the base (i.e. the…
With native Rust support recently announced for Cloudflare Workers, I wanted to take a moment and write about the possibilities, but also the obstacles as a sort of reality check for myself. I’m extremely bullish about Cloudflare, Wasm, Rust, edge computing, and the recently announced native Rust support. If I’m not careful, my enthusiasm could cloud judgement, so I figured I’d…