We just made Shopify's Admin 30% faster while setting it up for AI superpowers. Behind the scenes, we completely transformed how admin.shopify.com works—rebuilding a system that powers 67 million daily page views and merchants live inside to run their business. Here's how we did it.
The Challenge: Running at Truly Massive Scale
The scale of Shopify's Admin isn't just about traffic (though 67 million daily page views is nothing to sneeze at). What makes our challenge unique is the contribution scale.
When 101 different teams are shipping new features to the same codebase, with around 350 PRs merging daily, traditional architecture breaks down. Since 2020, our TypeScript codebase has more than doubled in size:
```
Total Files: 620,730
Lines of TypeScript: 3,184,248
Lines of Definitions: 33,854,456
```
This massive collaboration created real problems for merchants:
- Inconsistent loading patterns (sometimes skeletons, sometimes spinners)
- Duplicate data requests slowing down pages
- Different teams building similar features in conflicting ways
- Systems like Search and Sidekick maintaining separate "sources of truth" about routes
We needed a better way to manage this complexity without slowing down our developers or our merchants.
Enter Remix: Web Standards to the Rescue
When Shopify acquired Remix in late 2022, we saw an opportunity. Remix's focus on web standards and predictable data flow offered a path forward for our sprawling codebase. We set four clear goals:
- Create a single source of truth for all Admin routes
- Make pages load faster and more consistently
- Make developers' lives easier
- Prepare our UI architecture for AI
Two key developments made this possible: Remix adding support for Vite (our build system) and introducing SPA mode (perfect for Admin's single-page application architecture).
Route Manifests: From Chaos to Clarity
Before our rebuild, asking "how many routes are in the Admin?" would get you shrugs and estimates. Search maintained its own list of routes in YAML files. Sidekick had another list. When routes changed in the main codebase, these systems wouldn't know until something broke.
Our routing journey started in late 2022 when we began transitioning to React Router data mode. Initially, we had a massive file called getRoutes.tsx that returned a function defining all routes and their children. As you might imagine, this quickly became unwieldy.
The file ballooned into many sub-files defining child routes, becoming a constant source of merge conflicts given our 300+ daily PRs. Worse, since it was a runtime function, we had no clear model of all the routes in the Admin—just a file tree structure without a clear pattern that could only be evaluated at runtime.
This led to real problems:
- Different teams creating divergent loading patterns across routes(sometimes skeletons, sometimes spinners)
- Components loading their own data with duplicate requests
- Separate systems maintaining their own "source of truth" for routes
We knew we needed routes to be knowable statically, so they could be ingested by systems like Search and Sidekick at build time. We also needed metadata (descriptions, titles, eligibility, etc.) to be consistently available.
Our solution: route manifests—TypeScript files that:
- Live alongside their component code
- Contain all metadata about each route
- Get automatically globbed by Vite during build and development
- Build the route configuration for Remix
These manifests let us build tooling to create a complete sitemap of the Admin with all route metadata—a single source of truth that was easy for developers to contribute to. Since these files were typed and linted, we could enforce best practices.
Now we know exactly what we're working with: 1,017 routes, each with clear ownership and purpose. This means search, Sidekick, and other systems always have up-to-date route information.
Remix Loaders: The Performance Game-Changer
Previously, Admin pages loaded like this:
- Browser fetches component code
- Component code runs
- Then, data fetching begins
This created a waterfall effect where merchants waited for code to load before waiting again for data. With Remix loaders, we flipped the script:
- Browser fetches a tiny loader file (just 3.2kb for the Product Index route)
- Data fetching begins immediately
- Component code (a hefty 914kb for the same route) loads in parallel
This change alone dramatically improved load times. But we didn't stop there.
A Consistent, Beautiful Loading Experience
Before our Remix migration, merchants faced a patchwork of loading experiences. Some pages showed skeleton screens, others displayed spinners, and some had no loading indicators at all. This inconsistency made the Admin feel disjointed and less polished.
With Remix loaders, we could finally standardize the loading experience across all 1,017 routes. Here's what we built:
- A global loading indicator that shows merchants exactly when page transitions begin and end
- Smooth view transitions that maintain context between pages
- Intelligent loading states that eliminate the jarring "flash of empty content" merchants previously experienced
This consistency does more than just look good—it reduces cognitive load. Merchants no longer need to interpret different loading patterns as they move through the Admin. They always know exactly what's happening and when a page is ready for interaction.
This makes the Admin feel like a single, cohesive product rather than a collection of different tools.
The video above shows how smooth these transitions have become. Best of all, developers no longer need to build custom loading states for their features. The system handles it automatically, ensuring consistency while reducing code complexity.
Prefetching: Loaders Unlock New Performance Tricks
With loaders in place, we unlocked a powerful optimization technique that simply wasn't possible before: intelligent prefetching.
Here's why loaders make prefetching possible:
- Each route has a dedicated loader function that specifies exactly what data it needs
- These loaders are small (usually just a few KB) and can be executed independently
- We now have a standardized way to fetch data for any route without loading its components
When the browser becomes idle after a page load, we use that crucial downtime to:
- Identify commonly visited links from the current page
- Prefetch their loaders (not the full component bundles)
- Execute those loaders to warm the Apollo cache
Now when a merchant actually clicks to visit that page, the data is already waiting. No more waiting for API calls—the page can render immediately.
We paired this with persistent caching through Apollo's persistent storage with IndexDB. Since merchants typically return and spend lots of time in the Admin, this means their frequently visited pages load instantly, even between sessions.
These optimizations combined to deliver that 30% improvement in perceived load times. For merchants who spend hours in the Admin each day, this means less waiting and more doing.
Supercharging Sidekick with Remix Actions
Our new architecture doesn't just make pages load faster—it makes them more AI-friendly too.
With route manifests in place, we're now adding Remix actions and zod schemas to our routes. This means Sidekick can understand:
- What data each page needs
- What forms are available
- What validations those forms require
When a merchant asks Sidekick to "create a new product" the AI can:
- Determine the correct route
- Prefetch necessary data through the loader
- Apply the loader to the form schema
- Fill out form fields correctly
- Submit through POST to the action—all without loading unnecessary JavaScript
This architecture turns complex UI interactions into simple I/O functions that AI can easily work with.
What This Means for Merchants
If you're a Shopify merchant, these changes mean:
- Pages load 30% faster
- The Admin feels more responsive and consistent
- Sidekick can help you navigate and complete tasks more effectively
- New features arrive more reliably, with fewer bugs
All of this happens without you having to learn anything new or change how you work.
What's Next
With our new foundation in place, we're just getting started. The Admin's architecture is now ready for:
- More sophisticated AI integrations
- Faster feature development across all teams
- Even better performance optimizations
- A more consistent, polished experience throughout
Technical Architecture, Merchant Empowerment
Great architecture isn't just about clean code—it's about empowering merchants. By embracing Remix's simplicity and web standards, we've built an Admin that's faster today and ready for tomorrow's challenges.
In a system this large and complex, simplicity wins. And with Remix, we've found a powerful way to tame complexity while accelerating both our development process and the merchant experience.