Matteo Collina

Matteo Collina

@nodeland.dev

Platformatic.dev Co-Founder & CTO, Node.js TSC member, Lead maintainer Fastify, Board OpenJS, Conference Speaker, Ph.D. Views are my own.

4.6K followers374 following1.8K posts

Pinned

Node.js doesn't have a predictive way to manage traffic spikes, so over-provisioning for peak loads isn't optimized for the stable periods that follow. We've all faced this issue. This is why Platformatic is simplifying multithreading in our Node.js app server. 🧵 https://buff.ly/48yJoHD

youtu.beAddressing Overprovisioning & Performance Issues in Node.js via Multiple WorkersWe know scaling Node.js efficiently can be challenging—especially with the infrastructure costs that come from handling unpredictable traffic spikes. With Pl...
View full thread

Watch @jeff.auriemma.xyz break it down. He built an e-commerce storefront to show it. One slow field- product recommendations- held up the whole page. LCP was 4.1 seconds. Adding defer to the reviews and recommendations fragments dropped LCP to 1.1 seconds. 👉 youtu.be/jAV2evYLmXM

youtu.beYou should know about @defer in GraphQLBig Queries don't have to mean Slow Queries. Use the @defer directive to get your fastest and highest-urgency data on the screen faster without giving up the elegance that GraphQL offers.

It lets the server send the fast, urgent parts of a response to the client right away, while slow fragments stream in later. Still one single operation.

Ever wonder how much of modern @nodejs.org actually came from Deno? Luca and I did a whole session on it: the ideas, the features, and the friendly competition between the two runtimes. A really great conversation about how open source pushes each other forward.

I didn't pass the Anthropic Cyber Verification Program because I use the personal account sponsored by Anthropic. At this point, using top AI models for security is becoming a matter for the few elected. How are we supposed to keep Node.js and other critical infrastructure safe?

RAM is the new bottleneck. Every Node.js process is fighting for memory: containers, serverless, cloud bills, k8s limits. And here's the maddening part: V8 can use half the memory with one flag, and almost nobody turns it on.

View full thread

We decided to fix the "no binaries" problem. @platformatic has published multi-arch images of Node.js built with pointer compression enabled: Node.js 26 on trixie/slim/alpine. docker pull platformatic/node-caged

RAM is the new bottleneck. Every Node.js process is fighting for memory: containers, serverless, cloud bills, k8s limits. And here's the maddening part: V8 can use half the memory with one flag, and almost nobody turns it on.

View full thread

So why is it still rare? Because until recently, enabling pointer compression meant building Node.js yourself from source with `--experimental-enable-pointer-compression`. There were no prebuilt binaries. Most people just... never tried it.

The other thing holding it back: compatibility. N-API addons (bcrypt, sharp, @napi-rs/*, argon2) work fine. But old V8 native addons, like anything using `nan`, can segfault under pointer compression. That's the tax you pay.

RAM is the new bottleneck. Every Node.js process is fighting for memory: containers, serverless, cloud bills, k8s limits. And here's the maddening part: V8 can use half the memory with one flag, and almost nobody turns it on.

Pointer compression. V8 stores pointers as 32-bit offsets from a base address instead of full 64-bit pointers. That single change halves the size of every object in your heap.

Look at the numbers. Array of 1M objects: 40.47MB → 20.24MB. Nested objects (500K): 50.21MB → 24.64MB. Linked list: 19.08MB → 9.54MB. Every pointer-heavy structure drops ~50%.

The hottest take in the Node.js ecosystem last month: should npm ship TypeScript files? Everyone has an opinion. Few of them focus on what your users actually get. New episode of The Node (and more) Banter 🧵👇

View full thread

✅ The dist-vs-source tradeoff, and why a build step is not a tax but a guarantee ✅ Where the "no build" idea actually has merit, and where it does not

The hottest take in the Node.js ecosystem last month: should npm ship TypeScript files? Everyone has an opinion. Few of them focus on what your users actually get. New episode of The Node (and more) Banter 🧵👇

View full thread

There's also the ecosystem reality. Millions of packages, editors, and tools assume JavaScript. Make .ts the deliverable and you break the one thing that keeps npm working: the fact that a published package just runs.

In this episode @lucamaraschi and I get into: ✅ Why "ship the source" sounds right and is usually wrong ✅ The TypeScript features that break when you skip the build ✅ What happens to the package ecosystem if published output stops being JavaScript

The hottest take in the Node.js ecosystem last month: should npm ship TypeScript files? Everyone has an opinion. Few of them focus on what your users actually get. New episode of The Node (and more) Banter 🧵👇

The argument for distributing TypeScript is simple: it's the source of truth. Ship the .ts files, skip the build step, and the types are always in sync. Sounds great on paper. Falls apart in production.

The problem is compatibility. `import type`, enums, namespaces — TypeScript has a whole family of features that don't survive a trip through a runtime that strips types. Ship the source and you force every consumer to handle your dialect, not just the compiled output.

A @nodejs `VirtualFileSystem` pairs a storage provider (memory, a real directory, or a ZIP) with an fs-like API. Mount it, and `node:fs` operations and the module loader recognize it. No special asset API, no rewriting every dependency.

View full thread

One correction worth flagging: VFS is not a sandbox. Mounting doesn't stop code from touching other real paths or spawning processes. Untrusted code still needs a real isolation boundary.

A @nodejs `VirtualFileSystem` pairs a storage provider (memory, a real directory, or a ZIP) with an fs-like API. Mount it, and `node:fs` operations and the module loader recognize it. No special asset API, no rewriting every dependency.

View full thread

You can build a ZIP with `node:zlib` and mount it, then `import()` the entry point straight out of the archive. Your application code doesn't need to know which provider stores its files.

Native addons work too. The OS loader can't open a virtual path, so Node reads the bytes and creates a private, self-cleaning image (an in-memory fd on Linux, temp files elsewhere). Same for shared libraries via `node:ffi`.

A @nodejs `VirtualFileSystem` pairs a storage provider (memory, a real directory, or a ZIP) with an fs-like API. Mount it, and `node:fs` operations and the module loader recognize it. No special asset API, no rewriting every dependency.

Core support shipped across 26.4.0 → 26.10.0: module-loader integration, the ZIP provider, native-addon loading, Single Executable Application support, and VFS-backed `node:ffi`. Still experimental, it needs `--experimental-vfs`, but this is dropping soon!

The mount model changed from the original proposal. `mount()` takes no target; Node picks a reserved namespace for each instance. No more overlay questions like: does the virtual file win, or do we fall through to disk? Every path under a mount belongs to that VFS.

Matteo Collina reposted

I have sampled the @nodeconf.eu speaker gift (a bag of coffee) and I can confirm that it's pretty tasty! Thanks @nodeland.dev et al! (For the curious: I did 383ml to 23g, steeped for 2 min in a Clever Dripper, stir, another 30s, then release.)

In the era of AI, our network is what makes us valuable, and the work more enjoyable. (The work is mysterious and important). Go to more conferences.

Big shoutout to @GitHub this week. In two days, they shipped a stack of security advisory updates that maintainers have been asking for for a long time. 🛡️

View full thread

5. New SecurityAdvisory fields in the GraphQL API. cveId, sourceCodeLocation, githubReviewedAt, nvdPublishedAt, repositoryAdvisoryUrl, plus severities and isWithdrawn filters. One auth path, one rate limit budget, fewer round trips. github.blog/changelog/20...

github.blogNew fields for SecurityAdvisory GraphQL API - GitHub ChangelogYou can now read more of the GitHub Advisory Database directly from the GraphQL API without falling back to the REST API. The SecurityAdvisory object gained five new fields: cveId:…

As a maintainer who lives in these flows, this is a huge quality-of-life boost. Trying to triage vulnerability reports with a single free-text box and no way to share private context was painful. GitHub heard us. 👏

Big shoutout to @GitHub this week. In two days, they shipped a stack of security advisory updates that maintainers have been asking for for a long time. 🛡️

View full thread

4. Repository security advisory comments API (public preview). Until now, the triage discussion lived only in the web UI. Now you can list, get, add, and edit comments via the REST API, and get comment counts in responses. I can now fully automate this via my custom Pi configuration.

github.blogRepository security advisory comments API in public preview - GitHub ChangelogYou can now read, add, and edit comments on repository security advisories using the REST API, including advisories created from private vulnerability reports. Until now, the discussion on an…

Big shoutout to @GitHub this week. In two days, they shipped a stack of security advisory updates that maintainers have been asking for for a long time. 🛡️

View full thread

2. Rate limits for private vulnerability reports. Bulk and automated reports were burying the real ones. Now there's a daily per-user cap, you can set a custom repo limit, and add trusted reporters to an allow list. Legit researchers get through, spam doesn't. github.blog/changelog/20...

3. Confidential comments on repository security advisories. Post comments visible only to maintainers. No more moving your abuse/investigation notes to Slack when a reporter can see everything. Clearly marked, permission-aware, and audit-logged. github.blog/changelog/20...

Big shoutout to @GitHub this week. In two days, they shipped a stack of security advisory updates that maintainers have been asking for for a long time. 🛡️

1. Structured forms for private vulnerability reports. No more single free-text box. Now reporters fill in a summary, details, PoC (min 150 chars), and impact. You can even customize the form via .github/VULNERABILITY_REPORT.yml and require a CWE. Reporters can also disclose whether they used AI. 🎯

"Do You Still Read Code Written by AI?": The question every developer is asking their colleagues. Here's my honest answer: I use AI every day, and it's made me more productive than ever. But I still review every line that ships. Luca and I will unpack it all next Wednesday!

View full thread

"Do You Still Read Code Written by AI?": The question every developer is asking their colleagues. Here's my honest answer: I use AI every day, and it's made me more productive than ever. But I still review every line that ships. Luca and I will unpack it all next Wednesday!

View full thread

The moment I stop reviewing is the moment I stop being responsible for what I ship. AI is just another contributor now. I review its PRs like I review anyone else's, and I decide if it's good enough.

My worry isn't that software development is dying. It's that "I didn't review it, the AI wrote it" becomes an acceptable excuse. At AI speed, the scale of damage when you ship code you don't understand is enormous.

"Do You Still Read Code Written by AI?": The question every developer is asking their colleagues. Here's my honest answer: I use AI every day, and it's made me more productive than ever. But I still review every line that ships. Luca and I will unpack it all next Wednesday!

My bottleneck is no longer coding. It's review. When AI hands me a fix, I don't just check if the tests pass. I ask: does this actually close the attack vector? Are there edge cases the model missed? Is this the right fix, or just a fix?