
“Help us migrate this application to ISR” sounds like an implementation request. Find the right Next.js configuration, change a few routes, verify the cache behavior, and move on.
That was the request from a large enterprise software company I worked with. It was also an incomplete description of the problem.
Once we got into the application, the work spread across caching, revalidation, deployment behavior, application architecture, and the boundaries of a large monorepo. We had to separate platform constraints from implementation problems. We had to test assumptions that sounded reasonable in a meeting but did not always survive contact with the system.
This is the part of Forward Deployed Engineering that job descriptions tend to flatten. The role is often described as a mixture of software engineering, solutions engineering, and consulting. Those labels describe some of the activities. They miss the responsibility.
The role takes temporary ownership of an ambiguous engineering problem and carries it far enough that the customer’s team can own the answer.
Code may be part of that work. So may architecture, debugging, workshops, or a blunt recommendation to stop pursuing the proposed solution. The output is not a demo. It is less uncertainty in a real production environment.
Customers usually arrive with a solution already attached to the problem:
We need ISR.
We need an AI agent.
We need to migrate this workload.
The proposed solution is useful. It tells you what the team has been discussing and where they believe the constraint lives. Accepting it without investigation is risky.
In the ISR engagement, the framework feature itself was well understood. Incremental Static Regeneration lets a Next.js application update cached static content without rebuilding the entire site. That definition is simple enough to fit in a paragraph. Its behavior inside an existing system is not.
The useful questions were lower-level:
These questions changed the engagement. “Migrate to ISR” became a set of smaller decisions about rendering, invalidation, ownership, and rollout order.
That distinction matters because caching is a system behavior, not a switch. Next.js supports time-based and on-demand revalidation, and its own documentation calls out deployment concerns such as coordination across multiple instances. A route can look correct in isolation while the surrounding deployment model produces a different result. The right answer has to account for both.
Discovery is not the polite meeting before the engineering starts. It is engineering. The first deliverable is a model of the system that is accurate enough to make a consequential decision.
I think about forward deployed work as a loop with five distinct moves. A project may revisit any of them when new evidence appears.
| Move | Question being answered | Useful evidence |
|---|---|---|
| Discover | What is failing or preventing progress? | Production behavior, team constraints, previous attempts |
| Model | Which parts of the system explain that behavior? | Request paths, data flow, cache boundaries, deployment topology |
| Test | Which assumptions survive a real check? | Small code changes, traces, logs, production-like experiments |
| Introduce | What is the safest useful change? | An incremental migration step with a rollback path |
| Transfer | Can the customer team make the next decision without us? | Documentation, pairing, operational checks, shared reasoning |
The requested solution starts the investigation. Customer ownership finishes it. New evidence can send the work backward before it moves forward.
This loop explains why the role changes shape during a project. One hour may be spent tracing a rendering issue through an unfamiliar codebase. The next may be an architecture discussion about cache ownership. Later, the useful work may be writing a proof of concept or explaining why an apparently cleaner design creates an unrealistic migration.
The constant is not the activity. It is responsibility for closing the gap between what a product can do and what will work in this environment.
That requires a particular kind of speed. An FDE rarely has time to learn every historical decision in a codebase. The goal is to build a useful system model: how requests enter, where data comes from, what runs at build time or request time, which state is shared, how the application is deployed, where failures cluster, and how the team sees production.
Knowing every file is unnecessary. Knowing which boundary can change the outcome is not.
A demo answers a narrow and useful question:
Can this idea work?
Production asks a harsher one:
Can this idea keep working inside this organization after the people who introduced it leave?
The second question brings back everything a prototype is allowed to ignore: authentication, permissions, live traffic, failure modes, observability, security review, release processes, and the team that receives the pager.
This is why an architecture recommendation is rarely enough. Drawing the desired end state is often easier than designing a path from the current system. A plan that pauses feature work for months may be coherent on a whiteboard and useless to the organization. The same is true of a migration that creates value only after every application and team moves at once.
In the ISR project, the useful outcome was an incremental migration path. The team gained a clearer view of what the application needed to change and what the platform was responsible for. Just as important, their engineers had enough context to continue making those decisions without routing every question back through us.
That transfer is part of the implementation. Documentation, pairing, examples, and design discussions are not follow-up material added after the “real” engineering. They are how the customer becomes able to operate and extend the system.
Dependence is not proof of a successful engagement. It is unfinished work.
Forward Deployed Engineering is not the right label for every customer-facing technical task.
If a problem can be resolved by pointing to documentation or changing a known configuration value, it does not need temporary engineering ownership. If the work ends at a polished demo, it has not yet answered the production question. If the FDE becomes the permanent maintainer, ownership was never transferred.
The title also varies between companies. I would not evaluate the role by asking whether someone writes code every day or spends a fixed percentage of time with customers. Those are proxies. I would ask what uncertainty they are expected to own and how far they are expected to carry it.
For engineers considering the role, and for hiring managers defining it, these questions are more revealing:
The boundaries matter. An FDE cannot replace the customer’s product judgment, erase organizational constraints, or guarantee an outcome that depends on decisions outside the engagement. Temporary ownership still requires a clear transfer point. The job is to make the decision space smaller and the next move safer, not to become the owner of every adjacent problem.
The original request was to help migrate an application to ISR. The actual work was figuring out which parts should move, what had to be true for the new behavior to work in production, and how to sequence the change so the team could continue without us.
That is Forward Deployed Engineering: figure out what should be built, get it working in the real environment, and leave the people who own that environment able to carry it forward.
Thanks for reading.
More writing