Jay FreestoneJay Freestone
  • Feed
  • Readme
  • GitHub
  • Bluesky
  • RSS

I’m Jay, a product engineer based in East London. A polyglot at heart, I'm a Rust lover, a Go skeptic and a TypeScript apologist. Right now I’m helping shape the future of procurement software at Omnea.

  • Link•Sep 3, 2026

    Causewalk and error wrapping →

    I’m a big fan of error wrapping to provide more context.

    In Go, this is standard practice:

    // Hopefully something better than oh-no.
    // Think contextual information that the caller has.
    result, err := run()
    
    if err != nil {
      return fmt.Errorf("Oh no: %w", err)
    }Go

    But in JS, we’ve had this for a while too, via Error.cause:

    try {
      throw new Error()
    } catch (cause) {
      throw new Error("Oh no!", { cause })
    }js

    Go has a couple of nice utilities for walking the error tree to see if an error matches a particular type or interface (errors.As, errors.AsType, etc.). This is great when most of the time you don’t care about the specific error, but at the edge you do. For instance, an HTTP server might care if an error is of a certain type when choosing the right response status code.

    There are a bunch of error libraries out there, but I’ve just published a super tiny one that scratches my personal itch for these helpers: causewalk.

    Here’s an example:

    import { is } from "causewalk"
    import { CardDeclinedError } from "./payments"
    
    try {
      await checkout(order)
    
      return response.status(204).send()
    } catch (error) {
      // Does any error in the chain match `CardDeclinedError`?
      if (is(error, CardDeclinedError)) {
        return response.status(402).send({ message: "Card was declined" })
      }
    
      return response.status(500)
    }TypeScript

    I really do mean small: the surface area today is just three simple functions that share the same helper for walking errors. Copy-paste it, install it or use it as a starting point. I love things like neverthrow, but often they require too much investment and buy-in.

  • Link•May 16, 2026

    Coldstarts are dead →

    I have to admit, this one made me chuckle:

    The cold start argument had its day. That day was 2018. If you’re still leading with it, I get it, it used to be real. But the data has moved on, and it’s time we did too.

    Followed by:

    | Runtime    | P50       | P99       | Notes                 |
    |------------|-----------|-----------|-----------------------|
    | Node.js 22 | 200-350ms | 600ms-1s  | Solid general choice  |

    Sure doesn’t look dead to me! That’s the entire TTFB performance budget for a lot of sites.

  • Link•May 2, 2026

    GitHub's Ace with Maggie Appleton →

    GitHub’s had a rocky time lately, but Maggie Appleton’s talk at the AI Engineer conference was inspiring.

    Whether Ace itself takes off or not, I think GitHub are on the money here with where we’re headed.

Jay Freestone / mail@jayfreestone.com

Last Updated Sep 3, 2026