Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesUse Inngest to orchestrate a browser job, not to make the browser or target website infallible. Put retryable work inside clearly named step.run() boundaries, let successful step results be checkpointed, and design separately for browser state, duplicate external actions, timeouts, and cleanup. Playwright performs the browser actions; Inngest coordinates triggered work and resumes from completed steps. A managed browser service is optional.
What Inngest makes durable—and what it does not
Inngest functions are ordinary TypeScript, Python, or Go functions wrapped with trigger and execution metadata. An event, schedule, or webhook can start a run. Inngest describes its functions this way: “Inngest functions are durable: they throw errors or exceptions, automatically retry from the point of failure, and can be stateful and long-running.” That is a description of Inngest’s orchestration behavior, not a guarantee that a browser session or external website will remain available.
In a browser workflow, Playwright still drives pages, clicks, navigation, and data extraction. Inngest runs the surrounding work and records successful step results. If a later step fails and the run resumes, Inngest can reuse successful results rather than execute those earlier steps again. A stored step result is not a saved browser process: it does not, by itself, preserve an open page, cookies, local storage, or an authenticated session.
- Inngest: triggers, step boundaries, retries, and persisted results.
- Playwright: browser and page operations, including contexts that isolate browser state.
- Optional managed browser: a remote place to run the browser, with its own connection and session lifecycle.
The implementation below is an illustrative workflow pattern based on the documented Inngest step model, not a browser recipe published by Inngest. Adapt its imports and registration to the Inngest SDK version and app setup you use.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →#1 Best Overall
How to build a reliable browser workflow with Inngest
1. Define the trigger and the outcome
Start by deciding what starts the job and what counts as a useful, durable result. For example, a scheduled or event-triggered job might visit a public page, extract a small record, and store that record in your own application. Validate the input before launching a browser. Pass only the data the workflow needs; keep credentials in your secret-management configuration rather than in event payloads or logs.
2. Split work at meaningful durable boundaries
Use a separate step.run() for meaningful work that should be retried and whose successful result should be checkpointed. Give each step a stable, descriptive ID. A practical division is input validation, browser interaction, result persistence, and downstream notification. Do not place an entire multi-stage journey in one opaque step if you need earlier completed work to survive a later failure.
A simplified TypeScript outline:
const workflow = inngest.createFunction(
{ id: "capture-and-store" },
{ event: "capture/requested" },
async ({ event, step }) => {
const input = await step.run("validate-input", async () => {
// Validate and normalize event.data.url and any task identifier.
return { url: event.data.url, taskId: event.data.taskId };
});
const extracted = await step.run("visit-and-extract", async () => {
// Launch or connect to a browser, visit input.url,
// extract the required data, and close resources in finally.
return { title: "example", observedAt: new Date().toISOString() };
});
const saved = await step.run("persist-result", async () => {
// Store extracted data using an application-level idempotency strategy.
return { taskId: input.taskId, stored: true };
});
await step.run("report-completion", async () => {
// Notify a downstream system if needed; make this operation safe to retry.
return { reported: true };
});
return { saved };
}
);
This outline deliberately leaves browser launch, database access, and notification APIs as application-specific pieces; there is no single correct implementation for those systems. The important boundary is that each step returns serializable data needed by subsequent work, rather than relying on an in-memory page object surviving a retry.
3. Make retries safe for the destination
A retry can repeat an external action. For example, a browser may submit a form and then lose its connection before the step can report success. Inngest cannot determine whether the site committed that submission or undo it. Retrying the same action could submit twice.
Free tools Windows power users keep installed
One-click scans. No signup required.
For writes or submissions, make duplicate handling part of the application design:
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
- Use a destination-supported idempotency key when one exists.
- Use a stable task or operation identifier and check whether the intended result already exists before repeating a write.
- When the outcome is uncertain, reconcile against the destination’s current state before proceeding.
- Keep read-only extraction separate from consequential actions where possible, so a read retry does not accidentally repeat a write.
These safeguards are application-level patterns consistent with Inngest’s recommendation to make retried work idempotent. A stable step ID helps Inngest identify a step; it does not make a website submission idempotent.
4. Return results, not live browser objects
Persist compact, serializable outputs such as extracted fields, record IDs, or a status. Do not treat a browser, page, or context object as the durable output of a step. On resumption, successful Inngest steps can supply their saved result, while a browser interaction that must run again should establish its own browser connection and state.
How should browser state survive across steps?
Choose explicitly between isolation and continuity. Playwright browser contexts isolate cookies and cache from other contexts, making independent jobs easier to separate. A fresh context per task is a strong default for unrelated users or tenants. A multi-action task that depends on one login needs a deliberate session strategy instead.
Isolated task contexts
Create a context for the task, perform its work, then close it. This reduces accidental cross-task cookie or cache sharing and makes the task boundary clear. Do not reuse one logged-in context across unrelated tenants simply to avoid signing in again.
Intentional session continuity
If later actions require the same authenticated session, choose how that session will be recovered after a worker interruption. Options include securely restoring authentication state or using a browser provider’s documented persistent-session and reconnection behavior. The exact mechanism depends on the Playwright and hosting setup. Store authentication material securely, restrict who can access it, and avoid exposing it through event data, logs, or a public live-session URL.
Rank #3
Inngest’s persisted step state and browser session state are separate. A checkpointed result can tell a later step what happened, but it does not resume a live tab. Conversely, a still-open remote browser session does not mean Inngest has recorded the successful result of a step.
How should I handle browser timeouts and retries?
Inngest’s retry documentation says the default is up to four retries after the initial attempt for a function or step—up to five attempts total—and that the retry count is configurable, including zero. The documented model gives each step its own retry counter. In a multi-step function, retries at several steps can therefore create more total attempts than a single shared function-wide budget would suggest. Recheck the current Inngest documentation and configuration when setting operational expectations.
Place a browser interaction that should retry inside its own step. Set finite navigation and action timeouts in the browser code, and let a failure surface if the operation cannot complete; an unbounded wait can tie up a worker or remote session. Choose retry behavior based on the operation: retrying a read may be acceptable, while retrying a potentially committed form submission requires idempotency or reconciliation first.
A timeout is ambiguous: the browser may have stopped before the target acted, or the target may have acted while the browser failed to receive confirmation. On retry, first consider that uncertainty rather than assuming the website did nothing.
Should the browser run locally or on a managed service?
Local Playwright and remote managed browsers solve different operational problems; the available vendor documentation does not establish a universal winner for reliability, cost, or performance. Browserless documents managed browser access and several connection and session patterns. Choose for your workload based on the following factors:
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
| Decision factor | Local Playwright | Managed remote browser |
|---|---|---|
| Infrastructure | Your environment provisions and maintains the browser runtime. | The provider supplies browser access; verify the provider’s current connection and session behavior. |
| Worker interruption | Design how browser state is recreated or restored when a worker stops. | Design around provider session lifetime, timeout, and reconnection behavior. |
| Concurrency | Capacity depends on the resources and limits of your own deployment. | Check current plan and session limits; parallel sessions may count toward provider limits. |
| Network and compatibility | Validate that the runtime can reach the target and run the required browser dependencies. | Validate the provider’s network reachability and supported browser connection method for your workload. |
| Security | Control credentials, browser data, and network access in your own environment. | Assess credential handling, session access, and the provider’s connection model. |
| Cost | Account for the infrastructure and operations you provide. | Review current provider pricing, session limits, and the cost of sessions that remain open. |
Browserless documents that sessions have timeouts and that sessions waiting for human interaction remain active and billable. If a live interactable URL is available, its holder can control the logged-in browser; handle that URL like a bearer secret. Close sessions when the workflow no longer needs them.
Be precise about the Browserless “Standard Sessions” pattern: its documentation describes that pattern as Puppeteer-only and unreliable with Playwright because Playwright does not expose browser.disconnect(). Browserless documents other Playwright connection and session approaches, so do not generalize that limitation to every way of using Playwright with Browserless. Check the current documentation for the exact pattern you plan to use.
Cleanup, performance, and cost controls
Close resources on success and failure
Close pages, contexts, and browser connections in cleanup paths, including when navigation, extraction, or persistence fails. For remote browsers, also end the provider session using the lifecycle supported by that connection method. Bound any wait for a human to act; a paused workflow can still leave a browser session active.
Control resource use with bounded work
Use finite browser waits and avoid launching work without a concurrency plan. A slow target can extend worker and session occupancy; repeated retries can multiply that occupancy. Keep extracted results small, and move long-running or human-dependent browser sessions into an explicit design rather than leaving a page open indefinitely.
Measure the actual failure mode
Record enough structured information to distinguish input errors, navigation timeouts, browser disconnections, extraction failures, and persistence errors. Avoid logging passwords, session tokens, cookies, or sensitive page content. Track attempts and step outcomes in your own observability setup so you can tell whether failures cluster around the site, browser infrastructure, or your workflow code.
Recommended Free Tools
Best Value
Common failure modes and fixes
| Symptom | Likely cause | Practical response |
|---|---|---|
| An earlier browser action happens again after a later step fails. | The browser journey is one large step, or the earlier operation did not complete as a separately checkpointed step. | Split work into stable, meaningful step.run() boundaries and return the data later steps require. |
| A submission appears twice. | A timeout occurred after the site processed the first submission, and retry repeated it. | Use a destination idempotency key, check for the existing outcome, or reconcile before resubmitting. |
| A later step has no login even though the earlier step succeeded. | Inngest persisted a result, not the live browser session or its cookies. | Restore authentication securely or use a deliberately persistent session strategy; otherwise authenticate within the new task context. |
| Unrelated jobs see the same authenticated state. | They share a context or session. | Use isolated contexts for independent tasks and avoid cross-tenant session reuse. |
| A remote session remains active while no work proceeds. | The workflow is waiting on a person or failed to close the session. | Bound the wait, close resources in cleanup paths, and verify the provider-specific session ending behavior. |
| Playwright connection behavior differs from an example using Puppeteer. | The provider’s session pattern may depend on browser-library-specific connection support. | Check the exact documented pattern; Browserless Standard Sessions are the Puppeteer-only caveat, not a blanket statement about all its Playwright support. |
Or skip the browser setup
If the job is to capture a website screenshot rather than interact with a complex browser journey, ScreenshotNeo offers a screenshot API and MCP server. It can fit as one HTTP operation in an Inngest step; it does not replace Playwright for arbitrary page interaction or authenticated multi-step automation. See the ScreenshotNeo site and API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free screenshots.
FAQ
Are retries applied to the whole function or each step?
Inngest documents retries at the function or step level. A failed step.run() can retry without rerunning earlier successful steps whose results were persisted.
Can an Inngest step keep a Playwright page open for the next step?
Do not rely on that. Inngest’s persisted step result is distinct from a live browser process; explicitly restore state or use a session strategy designed for continuity.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Does a remote browser guarantee that a workflow will succeed?
No. A remote service changes where the browser runs and adds provider-specific session behavior. The target site, network, browser, and workflow can still fail.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

