from Hacker News

Make any TypeScript function durable

by tilt on 10/23/25, 5:03 PM with 73 comments

  • by Etheryte on 10/23/25, 5:59 PM

    Of all the syntax options they could've gone with, they settled on what I would say is arguably the worst. If you want a one-liner, decorators are widely used across different languages and Typescript supports them as well.
  • by AgentME on 10/23/25, 8:14 PM

    This seems pretty similar to Cloudflare Workflows (https://developers.cloudflare.com/workflows/), but with code-rewriting to use syntax magic (functions annotated with "use workflow" and "use step") instead of Cloudflare's `step.do` and `step.sleep` function calls. (I think I lightly prefer Cloudflare's model for not relying on a code-rewriting step, partly because I think it's easier for programmers to see what's going on in the system.) Workflow's Hooks are similar to Cloudflare's `step.waitForEvent` + `instance.sendEvent`. It's kind of exciting to see this programming model get more popular. I wonder if the ecosystem can evolve into a standardized model.
  • by halflife on 10/23/25, 6:43 PM

    So vercel is adamant on making nextjs apps behavior completely unpredictable and hidden behind tons of magic code?

    At least in any other framework library I can just command click and see why things are not working, place breakpoints and even modify code.

  • by moritzwarhier on 10/24/25, 4:52 PM

    Skipping the part that defines what a "durable" function means is typical Vercel.

    It's probably a common async functional programming term that I don't know.

    But when "algebraic effects" were all the rage, the people evangelizing them at least cared to explain first in their blog posts.

    This one instead straight jumps via AI agents (what does this have to do with TypeScript syntax extensions?) to "installation".

    No thanks.

    Edit:

    I've read the examples after commenting and it's understandable, still explained in a post-hoc way that I really dislike, especially when it comes to a proprietary syntax extension.

    Also the examples for their async "steps" look like they are only one step away from assuming that any async function is some special Next.js thing with assumptions about clients and servers, not "just" async functions with some annotation to allow the "use workflow" to do its magic.

  • by qianli_cs on 10/24/25, 12:15 AM

    I'm excited about this because durable workflows are really important for making AI applications production ready :) Disclaimer: I'm working on DBOS, a durable workflow library built on Postgres, which looks complementary to this.

    I asked their main developer Dillon about the data/durability layer and also the compilation step. I wonder if adding a "DBOS World" will be feasible. That way, you get Postgres-backed durable workflows, queues, messaging, streams, etc all in one package, while the "use workflow" interface remains the same.

    Here is the response from Dillon, and I hope it's useful for the discussion here:

    > "The primary datastore is dynamodb and is designed to scale to support tens of thousands of v0 size tenants running hundreds of thousands of concurrent workflows and steps."

    > "That being said, you don't need to use Vercel as a backend to use the workflow SDK - we have created a interface for anyone to implements called 'World' that you can use any tech stack for https://github.com/vercel/workflow/blob/main/packages/world/..."

    > "you will require a compiler step as that's what picks up 'use workflow' and 'use step` and applies source transformations. The node.js run time limitations only apply to the outer wrapper function w/ `use workflow`"

  • by trevor-e on 10/23/25, 8:49 PM

    So this seems similar to https://temporal.io/, am I reading this right? I used that briefly a few years ago and it was pretty nice at the time. It did make some features much easier to model like their welcome email example. Would love to hear from someone with extensive temporal experience, iirc the only drawback was on the infra side of things.
  • by tom1337 on 10/23/25, 6:23 PM

    So at it's core this is "just" a toolkit to add automatic retries to functions inside another function? I don't know if the audience Vercel is targetig knows about idempotency as well as they should before plastering all their functions with "use workflow".

    I guess in the end it's another abstraction layer for queues or state machines and another way to lock you into Vercel.

  • by zzixp on 10/23/25, 7:11 PM

    This is actually pretty cool. We have a similar custom library at Xbox that's used extensively across all of our services.

    I do wish that there was some kind of self-hostable World implementation at launch. If other PAAS providers jump onto this, I could see this sticking around.

  • by TimTheTinker on 10/23/25, 7:33 PM

    I'd rather be explicit about what's going on at each step. That way idempotent functions can be handled differently, retry limits can be applied, and no separate preprocessor is required.

        export async function welcome(userId: string) {
          const user = await retry(() => getUser(userId));
          const { subject, body } = await retry(() => generateEmail({
            name: user.name, plan: user.plan
          }));
          const { status } = await retry(() => sendEmail({
            to: user.email,
            subject,
            body,
          }), 2);
          return { status, subject, body };
        }
  • by heldrida on 10/24/25, 12:58 PM

    Is this a durable execution engine/solution?
  • by sevender on 10/24/25, 7:02 AM

    Shameless plug: I’ve been working on a similar thing for Golang: zenyth.dev

    Durability is achieved by running the workflows in a wasm runtime.

  • by pavel_lishin on 10/23/25, 6:57 PM

    Am I stupid, or does the page not actually explain that workflow is?
  • by bern4444 on 10/24/25, 2:22 AM

    > For instance, Math.random and Date constructors are fixed in workflow runs, so you are safe to use them and the framework ensures that the values don't change across replays.

    How do you create an environment where everything is deterministic? Do they invoke every supported non deterministic function when creating the environment and rewrite those functions to return the values from the environment's creation time? Is there something more complex happening?

  • by drawfloat on 10/23/25, 6:30 PM

    Use client and use server aren’t great, but the fact they had to be declared at the top of a file was at least clear.

    Starting to scatter magic strings throughout a code base feels like a real step back.

  • by game_the0ry on 10/23/25, 11:00 PM

    Guillermo + Vercel should slow down and concentrate more on fixing the bugs with nextjs instead of adding more features no one asked for.
  • by 0xb0565e486 on 10/23/25, 6:24 PM

    Somewhat related since this about "workflows" and not cloud function, but are there any practical benefits to cloud functions other than the fact that it's cheaper for the providers as they don't have to run an entire bespoke runtime for every customer/application?
  • by dangoodmanUT on 10/23/25, 7:26 PM

    im becoming increasinglymore convinced that workflows are the wrong model

    just build state machines folks

  • by khalic on 10/23/25, 7:21 PM

    This seems... bad, inelegant.
  • by lloydjones on 10/23/25, 8:04 PM

    "use turnMyBrainOff";

    "use blackBoxWrapperForEverything";

  • by jadbox on 10/24/25, 1:23 AM

    "Next.js only" Thanks, no thanks. Neat idea though. (I'm mostly using Bun+React)
  • by sampli on 10/24/25, 3:30 AM

    This is a horrid pattern to try to get people to rely on. Stop with the magic
  • by LewisJEllis on 10/23/25, 8:03 PM

    can anyone point to the "Durable" part?

    looking at the docs and examples, I see Workflows and Steps and Retries, but I don't see any Durable yet. none of the examples really make it clear how or where anything gets stored

  • by oulipo2 on 10/23/25, 9:40 PM

    It's not really clear how you "update" a workflow/step method?

    What happens if you saw a bug, or you want to update and change a workflow? Is there a way to discard / upgrade the existing in-memory workflows that are being executed (and correspond to the previous version) so they are now "updated"?

  • by fullstackchris on 10/24/25, 2:16 AM

    I can almost with 100% certainty see this being one of those things that ultimately, after years of just blantantly ignoring something as simple as basic syntax rules, being redefined to something that is actually valid JavaScript / TypeScript.
  • by ssijak on 10/23/25, 7:21 PM

    Lost me at "use workflow" directive. This and Next16 expanding the set of directives just makes me question if I'm the mad man for thinking they are absolutely terrible.
  • by 8note on 10/23/25, 8:10 PM

    well that's some scary typescript syntax. i didnt know a string constant at the top of a function could change the operation.

    or is this some extra compilation step to rewrite the code?

  • by nawgz on 10/23/25, 11:17 PM

    Docs seem really underbaked.

    - where does the state and telemetry get stored?

    - if something is sleeping for 7 days, and you release a new version in that time, what is invoked?

    - how do you configure retries? Looks like it retries forever

    And I echo the hatred of the magic strings. Terrible dx

  • by quacky_batak on 10/23/25, 6:20 PM

    i hate the new pattern of using these magic strings everywhere. “use workflow”, “use client”, etc etc.

    I don’t like having custom bundler logic for my code.