Living on the Edge: Netlify’s Own Architecture
Netlify has spent years telling developers that the Jamstack is the right way to build. But does the company actually run its own products that way? In this episode of the Smashing Podcast, host Drew McLellan sits down with Leslie Cohn-Wein, a staff engineer at Netlify, to talk about the realities—and the payoffs—of the company dogfooding its own platform.
Building a Full App on a CDN
Cohn-Wein explains that Netlify’s front-end teams build some of their most visible properties—including the main company site and the docs portal—as static sites served entirely from a CDN. The benefits are the ones Netlify promotes to its users: faster response times, better security posture, and a simpler deployment story.
But the exercise is not purely marketing. The team has hit real friction along the way. Cohn-Wein notes that while the Jamstack works great for content-heavy pages, the trickier parts come in when you need site personalization, authentication, or dynamic functionality. The solution is often not to move the whole app off the CDN, but to lean on serverless functions to handle the pieces that need compute.
That means using Netlify Functions to process forms, gate content, or handle integration requests. By carving out those specific tasks, the team keeps the core of the site as a fast, cached deliverable, while still supporting features that need a layer of logic between the client and a service or database.
Deploy Previews and the CI/CD Loop
A cornerstone of Netlify’s own workflow is the deploy preview. For Cohn-Wein, the ability to spin up an atomic preview from any pull request is not a nice-to-have—it’s fundamental to how her team reviews work. Rather than reasoning about how a branch might behave in production, reviewers can visit an exact copy of the site as it will render, tied to a specific code commit.
Because the deployment is atomic, the preview swaps in instantly without a state where half of the assets are old and half are new. This makes the review cycle tighter. Designers don’t need code running locally, and engineers can check the impact of changes before merging anything. Cohn-Wein describes this as the difference between “discussing what the change might look like” and actually evaluating it in the environment it will ship in.
Dealing With Distributed Team Realities
The interview also touches on how a distributed engineering team shapes the way Netlify develops its own code. With contributors spread across time zones, async communication is the norm. Cohn-Wein notes that the Jamstack architecture supports this: because the source of truth lies in git repos and the deployed artifacts are immutable, teammates can work on disconnected areas of the site without stepping on each other.
Feature flags and release toggles enter the picture here as well. Even though the platform serves static files, code rollout still benefits from staggered release. Netlify handles this internally with the same dashboard controls its users get, giving the team the ability to shift percentage of users onto a new build without redeploying.
A Practical Endorsement
Asked whether she views the approach as a compromise, Cohn-Wein frames it as a direct fit. “We want everything to be a static asset where possible,” she says. The conviction that the architecture is right comes from having to maintain opinions of the product in production on it daily. If friction appears in the flow, it’s a signal for the platform team to solve the problem—not for the site team to move off modern architecture.
For practitioners, the lesson here is that “dogfooding” is not just a habit—it’s a feedback loop. Because Netlify uses its own product for the very properties its marketing page advertises, the team closest to the ground floor of the user experience is the same team with direct access to fix what pulls.
Show Notes
Here are the links mentioned during the show: Leslie’s personal site, Leslie on Twitter, and the Netlify platform.
Weekly Update
- A Dive Into React And Three.js Using react-three-fiber
written by Fortune Ikechi - Best Practices For E-Commerce UI Design
written by Suzanne Scacca - Authenticating React Apps With Auth0
written by Nefe Emadamerho-Atori - From The Experts: Global Digital Accessibility Developments During COVID-19
written by Robin Christopherson - What’s New In Vue 3?
written by Timi Omoyeni
From Static Sites to Full Apps
Netlify’s frontend team builds the service’s own dashboard as a Jamstack application — a React app that uses client-side data fetching and deploys itself on Netlify’s infrastructure. Leslie Cohn-Wein, staff frontend engineer at Netlify, describes this as dogfooding what a Jamstack app can be, pushing beyond the assumption that the architecture is only suitable for static sites with lightweight API integrations.
There are two strategies the dashboard relies on: pre-building content where possible, and fetching the more dynamic data client-side at request time. “We serve sort of a static shell of the app and then we fetch the user’s information from our internal REST API at the request time,” says Cohn-Wein. Much of the interaction with external services, such as pulling a list of repositories from GitHub, happens largely between the browser and that provider, not through Netlify’s core backend. A serverless function might inject secrets, but the bulk of that workflow happens in the browser.
That model changes the frontend engineering role. Although the dashboard uses React with Redux and PostCSS, with CSS architecture experiments underway, a large part of the job is now handling API layers. “Working on a Jamstack app at scale has pushed me to be a better developer,” says Cohn-Wein. She notes it stretches traditional frontend boundaries into backend territory.
Deploy Previews as Staging
Deploy Previews replace a conventional staging environment. Opening a Pull Request in GitHub automatically triggers a preview build of the app, which becomes the place where tests run and code review happens manually. Since previews are built with production environment variables, engineers trust that a working preview means a working production app. “We really trust that it’s going to match production,” says Cohn-Wein.
A single Pull Request can generate more than one site. The team’s repository is connected to multiple Netlify sites: the app, its Storybook UI component library, and a webpack bundle analyzer that produces a treemap of the app’s bundles. Each of those gets generated and linked for review in the Pull Request, keeping bundle size visible to developers.
Merging the Pull Request kicks off the production build automatically through Netlify’s continuous deployment. Engineers watch the logs in the real app rather than a preview tab and refresh to see the changes live.
Instant Rollbacks
If a release introduces a bug, the recovery path is designed to relieve pressure. Netlify's deploys are atomic, so every deploy in the dashboard’s history is a rollback target. The first step is to click “stop auto publishing” in order to break the connection to GitHub and block any further merges from restarting the problem.
From there, the engineer finds the last known working deploy in the list and publishes it. Once the app is back up, the production issue can be fixed via a Git revert on the main branch or a hot fix branch without worrying about urgency.
Recovery is even possible when a bug breaks the app UI itself. Because Deploy Previews hit the same production API, a preview URL left over from a previous Pull Request can serve as a fallback interface for publishing the older, working deploy. Backend engineers can also publish an older deploy from internal systems. “It’s totally recoverable from,” says Cohn-Wein, noting that the rollback ability was a “lifesaver” during her agency days.
Feature Branches vs. Feature Flags
For longer feature efforts, the team has shifted away from long-running feature branches. Previously, work was split into smaller PRs routed into a single feature branch that offered one preview environment. This required orchestration across teams before final merge: backend API changes and doc updates had to go live together. Netlify’s co-founder and CEO, Matt Biilmann, once launched the analytics feature onstage using a locked Deploy Preview at a Jamstack Conf, demonstrating this coordinated, one-shot event.
That model works but tends to accumulate an unwieldy final Pull Request and creates coordination overhead. Now, most larger work relies on LaunchDarkly feature flags around the new UI. This keeps main-branch merges — and therefore deploys — happening all the time, while the flag stays off in production and hides the new UI from most users.
A config variable alone doesn’t deliver the granular control that LaunchDarkly provides. The team can enable the flag in Deploy Previews for internal testing while leaving it off in production; they can also roll out to a selected percentage of users or target segments. “It allows you a lot more control over who you’re sort of releasing to,” says Cohn-Wein. Depending on which tab is open, engineers must check whether they are viewing the app itself or a preview with a different flag state.
Flag cleanup usually happens around two weeks after a launch. Slack notifications from LaunchDarkly act as a reminder to remove the feature flag code. The window in between is deliberate: it keeps a one-click rollback available while the fix is still being watched for problems in production.
Launches now feel less dramatic. Rather than the big button-press moment of merging a large feature branch and watching build logs, the team holds a Zoom call, confirms readiness, toggles a single flag, and the feature is live. “It relieves some of that pressure, anxiety,” says Cohn-Wein, “and it’s just that one click.”
Netlify has not yet fully unified this across all of its systems. The goal is a central LaunchDarkly key used by application code, API code, and doc site so that one toggle releases all components. That coordination is still in progress.
Eating Your Own Cooking
Being both the product and a primary consumer produces a steady stream of improvements.
The Team Overview, the app’s landing dashboard, exists partly because of that feedback loop. The initial quick version of the screen featured a “latest builds” card, but the entries didn’t link directly into the build log. Cohn-Wein noticed the omission while working on a personal project over the weekend, and added the links the next morning.
A system improvement came out of the same situation. Netlify Forms runs automatically on every build unless disabled. Form detection parses HTML at deploy time, adding processing time and slowing builds in general — including for the Netlify app itself, which doesn’t use forms at all. Netlify now offers a site setting to disable form detection because the extra step doesn’t help every user. “We don’t need this extra step in our own product,” Cohn-Wein says, and noted the need voiced by other customers, too. For metered users this brings faster builds and conserves allowances.
The product roadmap gets informed when internal challenges indicate what lower-level users might eventually encounter. However, Cohn-Wein cautions that anecdotal experience is not treated as equivalence with the entire user base. Netlify's broader research and data science teams complement that internal perspective, weighing professional or agency needs against entry-level scenarios, like managing blogs and personal sites.
Functions All the Way Down
A subsystem used for screenshots in the UI is a notable example of recursive product usage. When a site has deployed, the dashboard shows an image representing the homepage using Puppeteer, captured by a Netlify Function — a serverless setup. That function returns the image’s URL for display. Like CodePen’s similar approach, it’s not necessarily deeply hidden implementation detail, yet it’s essential to see it in action. “We use this end point that is a Netlify function inside our own app,” says Cohn-Wein.
The setup reinforces owning the back-of-the-frontend — the JavaScript and API-calling skills on the team.
Testing and Build Challenges
Not everything is entirely smooth. Build times remain a consideration, creating a balance between fast builds and the tests developers want to run before deploying. In it, Cohn-Wein consolates the frustration by remembering that when they spend extra time in the build, performance for end users typically benefits.
Critical flows in the app are end-to-end tested using Cypress, and the tests run against the Deploy Previews on each Pull Request through a GitHub action. Cypress runs in the pipeline can result in long, slow reviews. She sees an opportunity to improve testing. Potentially, tests could trigger as Netlify Functions off of a “deploy succeeded” event, which would rely more on the product; or, the testing could target production and use alerts, a model still on the drawing board.
As the team grows, Git-based workflows also face classic human coordination problems, and there’s no easy answer. When a broken main branch was pushed and then rolled back, every teammate has to hear about it and rebase.
Future frontend enhancements under discussion at Netlify include better collaboration, via assigning responsibility to builds, checking who changed site settings by looking at more granular audit logs, and introducing an organizational layer for sites assigned within the dashboard. Dev tooling work includes deep links and focusing directly on errors in build logs. Additionally, background functions and edge handlers could power localized content and other far-reaching features. With localization first on edge handlers, ample headroom remains to define the full limitations—or wherever the app goes next, using the methods it provides.



