[HN Gopher] Make Any TypeScript Function Durable
       ___________________________________________________________________
        
       Make Any TypeScript Function Durable
        
       Author : tilt
       Score  : 73 points
       Date   : 2025-10-23 17:03 UTC (5 hours ago)
        
 (HTM) web link (useworkflow.dev)
 (TXT) w3m dump (useworkflow.dev)
        
       | Etheryte wrote:
       | 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.
        
         | javcasas wrote:
         | My bad, this is open telemetry stuff to check the status of
         | your servers, not for vendors to extract as much data as they
         | can from you.
         | 
         | > I'm trying to find how they implemented the "use workflow"
         | thing, and before I could find it I already found
         | https://github.com/vercel/workflow/blob/main/packages/core/s...
         | 
         | > Telemetry is part of the core.
         | 
         | > Yuck.
        
           | nakovet wrote:
           | It's on the landing page, there is not even a standalone mode
           | yet, so you can't use it with node.js you need to use with
           | Next.js. All to say, it's just early alpha preview, I would
           | wait the project to mature before considering using it
           | anywhere.
        
             | javcasas wrote:
             | My bad, this is open telemetry stuff to check the status of
             | your servers, not for the vendor to slurp as much data from
             | you as possible.
        
               | evilduck wrote:
               | This is Open Telemetry functions you're referencing.
               | Being able to trace, profile and debug your own code
               | that's executing in a highly distributed environment is a
               | pretty useful thing. This isn't (necessarily) user
               | behavior telemetry.
               | 
               | At least understand what you're looking at before getting
               | the ick.
        
               | javcasas wrote:
               | That's fair. I'm too accustomed to seeing the other type
               | of telemetry shoved in all over the place.
        
               | skrebbel wrote:
               | Good luck running a server without any sort of telemetry.
               | How will you debug stuff without logs and traces? Seems
               | to me that the priorities are with practical, real
               | everyday engineering concerns.
        
           | oompydoompy74 wrote:
           | It's apparently an swc compiler plugin.
        
         | tom1337 wrote:
         | Yea but it's a vercel product and they also pushed the 'use
         | server' and 'use client' directives and probably want to build
         | on them.
        
           | bn-l wrote:
           | Absolutely bizarre decisions.
        
         | ajkjk wrote:
         | or no-op functions like useWorkflow() (with some kind of stub
         | that prevents dead code elimination).
        
         | MrJohz wrote:
         | Decorators don't work for functions, unfortunately, so wouldn't
         | work in this case. You'd need to add a bunch of class
         | boilerplate to make it work.
         | 
         | JavaScript didn't have a lot of great options for this kind of
         | statically-declared metaprogramming, which is why the "use X";
         | syntax has become so popular in various spaces. It's definitely
         | not my favourite approach, but I don't think there's any clear
         | "best" solution here.
        
           | halflife wrote:
           | You can use generator fns to achieve the exact same thing
           | without magic strings or bundles. And the bonus is that you
           | can debug it.
        
           | Etheryte wrote:
           | Since this magic string requires a preprocessor step anyway,
           | there's no reason they couldn't make it a decorator that
           | works on functions. I don't see the problem?
        
             | ngruhn wrote:
             | But then it's not valid TypeScript anymore. So all the
             | other tooling breaks: syntax highlighting, LSP, Linter, ...
        
               | Etheryte wrote:
               | Looking at the AST [0], this doesn't seem to be the case.
               | Since Typescript already supports decorators in other
               | contexts, it successfully parses everything and
               | identifies the decorator to boot. Since you're working in
               | a preprocessor context anyway, there's a number of
               | options to make all of this work well together.
               | 
               | [0] https://ts-ast-
               | viewer.com/#code/GYVwdgxgLglg9mABMOcAUBKRBvAU...
        
               | Noghartt wrote:
               | Instead of decorators, it could be just a higher-order
               | function. Which could handle it easily and in any
               | scenario that interchanges between TS/JS.
        
               | Etheryte wrote:
               | Well yes, that's the sane way anyone would reach for
               | first, but that's clearly not new-age enough by Vercel's
               | standards, so here we are. Similar to the other magic
               | string interactions, all of this is a roundabout way of
               | introducing platform lock-in.
        
       | quacky_batak wrote:
       | 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.
        
         | javcasas wrote:
         | Custom bundler + telemetry already included. Smells way too
         | much like Microsoft, too much like lock-in with a deal that
         | gets worse and worse.
        
         | brazukadev wrote:
         | "don't use next"
         | 
         | "don't use react"
        
       | tom1337 wrote:
       | 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.
        
       | 0xb0565e486 wrote:
       | 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?
        
       | drawfloat wrote:
       | 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.
        
         | c-hendricks wrote:
         | There's nothing about "use server" that requires it to be at
         | the top of the file though, it can go in function bodies and
         | you have a typed RPC method.
         | 
         | I think "use client" is the only one that has to go at the top
         | of a file.
        
           | TimReynolds wrote:
           | You are correct. Use server can be slapped in many places
        
       | halflife wrote:
       | 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.
        
         | lopatin wrote:
         | It's a great business model with epic lock in. Bored front end
         | devs keep indulging / enabling it so why stop?
        
       | pavel_lishin wrote:
       | Am I stupid, or does the page not actually explain that workflow
       | is?
        
         | davey48016 wrote:
         | It doesn't explain it on the landing page. Even skimming their
         | docs, it seems like you mostly have to infer the purpose of
         | this based on the features.
        
       | zzixp wrote:
       | 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.
        
         | lloydatkinson wrote:
         | Azures Durable Task Framework or something else? I guess
         | there's nothing public on it, which is a shame because it
         | sounds interesting
        
         | schniz wrote:
         | Hi I'm Gal from the team. Thanks! We did ship a reference
         | Postgres implementation. It would receive more love now that we
         | open sourced, but we can't call it "production ready" without
         | running it in production.
         | 
         | But we did have convos in the last couple of days on what we
         | can do next on the pg world ;D
        
       | khalic wrote:
       | This seems... bad, inelegant.
        
         | lioeters wrote:
         | Not only is it ugly in terms of language design, the feature
         | depends on over-engineered frameworks like Next.js and Nitro.
         | Magic string literals that rewrite your functions? No thanks.
        
       | ssijak wrote:
       | 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.
        
       | dangoodmanUT wrote:
       | im becoming increasinglymore convinced that workflows are the
       | wrong model
       | 
       | just build state machines folks
        
         | rubenfiszel wrote:
         | workflows is just short for state machine DSL
        
           | dangoodmanUT wrote:
           | but with history length and replay determinism landmines
        
       | TimTheTinker wrote:
       | 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 };         }
        
       | LewisJEllis wrote:
       | 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
        
         | schniz wrote:
         | That depends on the "world". We built an adapter interface so
         | you could store the data (and other things) anywhere you want.
         | There are some docs which are wip regarding that:
         | https://useworkflow.dev/docs/deploying/world
        
       | lloydjones wrote:
       | "use turnMyBrainOff";
       | 
       | "use blackBoxWrapperForEverything";
        
       | 8note wrote:
       | 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?
        
         | koolba wrote:
         | Must be some compile step. Reminds me of "use strict".
        
         | art0rz wrote:
         | "use strict" has been around since 2009. That being said, this
         | is not a TypeScript or React feature but yet another black box
         | magic NextJS feature to try to lock you into the Vercel
         | ecosystem.
        
       | AgentME wrote:
       | 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.
        
       | trevor-e wrote:
       | 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.
        
         | oulipo2 wrote:
         | And to DBOS too
        
       | oulipo2 wrote:
       | 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"?
        
       ___________________________________________________________________
       (page generated 2025-10-23 23:00 UTC)