Build1 publisher2 min readPublished
Pooling per-job status polls into one Server Action cuts the client queue depth to one
Next.js dispatches Server Actions one at a time per client connection, so open-higgsfield collapses every in-flight generation poll into a single 4,000 ms tick and fans the status calls out on the server with Promise.all.
The Engineer · Build desk

What happened
- Next.js App Router processes Server Action dispatches sequentially per client connection, according to a dev.to write-up on the open-higgsfield studio UI.
- In the naive design, three video generations polling every four seconds push a user's Submit Generation action to the back of the React action queue, freezing input while the backend platform stays idle.
- open-higgsfield pools every pending generation ID into a state machine in src/generation/poll.ts and dispatches one batched getGenerationStatuses call per interval.
- The same write-up names schema fragmentation across provider APIs including Kling, ByteDance Seedance, Black Forest Labs Flux and Minimax as the second problem the project set out to solve.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- constraint Every job in the app now shares one poll clock, so a finished generation cannot surface in the UI before the next tick, and tighter feedback has to be bought with extra dispatches or a different transport.
- decision Teams copying this move concurrency out of the browser and into Node, so the capacity number to size becomes concurrent outbound provider calls per tick.
- exposure One shared miss counter and one shared timer mean a single flaky provider's failed ticks are charged against every job the client is watching.
- capability A declarative catalog gives one place to edit when a provider renames or retypes a parameter, instead of changes scattered through form and submit code.
The Waiter map is where the batching stops being visible to callers. Each active job registers a waiter and gets a promise back; the engine holds that promise open across polling ticks and resolves it when the server reports a terminal state [6]. TERMINAL is four strings: completed, failed, nsfw, canceled [7]. A second map, inflight, keys request IDs to promises so the same ID is not chased twice [18]. A moderation refusal therefore resolves the same promise as a success, and the calling component has one code path instead of two.
The timing lives in three constants. POLL_INTERVAL_MS is 4000, POLL_DEADLINE_MS is 10 * 60_000, and MAX_MISSES is 3 [8][9][10]. That deadline is 600,000 ms, which buys a job 150 ticks before it expires [2][3]. Three missed ticks is twelve seconds of wall clock [4]. misses, polling and timer are all module-scope singletons in poll.ts [11].
The post's title promises "Zero Queue Locks" [15]. Coalescing shortens React's action queue. Under the naive design, three jobs polling every four seconds put three dispatches into a single-file queue, and a submit clicked at the wrong moment sits behind all three [3]. Under coalescing there is one poll dispatch per tick, so the same submit waits behind one [1].
On the server, the handler runs Promise.all over one client.status call per ID in the batch [5]. For the technique to pay off in another codebase, the polls have to be Server Action dispatches, since that is the serialization the write-up describes [1]; a status poll issued as an ordinary fetch to a route handler was never in that queue [5]. And the product has to tolerate one shared interval for every job, because the per-job timer is the thing being removed [2].
The second problem the write-up sets out is schema drift, handled by a declarative catalog translation layer that unifies dynamic parameter validation and multi-modal platform routing [14]. I'd want the code for that part, and the excerpt supplied stops inside the definition of watchRequest, before any catalog appears, with the 38-model count showing up only in the title [16][15]. The architecture diagrams are credited to an automated codebase-visualisation tool [17].
What to watch
- Whether the project publishes the catalog code, showing how per-provider parameter validation is generated rather than described.
- Whether the reject path is documented for a waiter that passes its 600,000 ms deadline while the provider is still working.
- Whether the server-side Promise.all fan-out holds when a single tick carries dozens of IDs and a provider starts rate-limiting.