This article concerns how we handled performance optimization on our enterprise-scale eCommerce platform, built with Next.js and deployed on Vercel. We went from sluggish load times, unstable layouts, and red Core Web Vitals to a perfect Speed Insights score, improving from around 60 to consistently above 95. Along the way, we rethought our rendering strategy, reduced JavaScript bloat, restructured our API layer, and set up continuous performance checks. The payoff was huge: faster pages, better rankings, and higher conversions, all while serving over 12 million visitors every month. I’ll walk through the technical details, including rendering strategy, caching, minimizing JavaScript, and monitoring performance continuously.

Introduction

In the fast-paced world of eCommerce, website performance is critical to success. A slow-loading site frustrates users and negatively impacts your SEO rankings and conversions. Core Web Vitals, such as LCP, INP, and CLS, are crucial metrics that determine your site's performance and affect how Google ranks your pages.

Optimizing an enterprise-scale eCommerce site like ours, built with Next.js, comes with its own set of challenges. These challenges range from balancing performance with content freshness to optimizing media and caching strategies. With the help of Vercel, we were able to fine-tune our site to achieve a perfect Speed Insights score, resulting in faster load times, improved SEO, and a better user experience.

Understanding Speed Insights and Core Web Vitals

Before diving into the technical details, it's important to understand why these metrics matter. Speed Insights and Core Web Vitals are tools and standards developed by Google to help site owners measure and improve real-world user experience. They focus on how quickly your site loads, how soon it becomes interactive, and how stable the content is as it loads. Optimizing for these metrics improves user satisfaction and directly impacts your site's SEO and conversion rates.

What Are Core Web Vitals?

Core Web Vitals are a set of specific metrics that Google considers essential for delivering a great user experience on the web. They measure the most critical usability aspects: loading performance, interactivity, and visual stability. By focusing on these, you can ensure your site feels fast and reliable to visitors, which is especially important for e-commerce platforms where every second counts. Google’s official documentation on Core Web Vitals and Page Experience outlines how these metrics influence your site’s search rankings and provides tools to help you measure and improve them.

 

LCP (Largest Contentful Paint): This tells you how long the most significant and most crucial piece of content is to appear, usually a large image or headline. It's the part that makes the page feel "ready" to use. If this shows up in under 2.5 seconds, people won't feel like the page is slow. When you open a news site, LCP measures how quickly the main story or photo shows up, not just the menu or background. To dive deeper into practical techniques like image preloading, reducing render-blocking resources, and improving server response time, check out Google’s guide on optimizing Largest Contentful Paint.

 

INP (Interaction to Next Paint): This tracks how quickly something happens on the screen after you click, tap, or type. It measures if there's a noticeable delay when you expect a reaction. The page should respond in under 200 milliseconds, it should feel instant. If you tap a "Buy Now" button, it checks how quickly you see the following screen or loading spinner. A delay here feels frustrating. If you’re tackling sluggish interactions or slow UI responsiveness, this resource on improving Interaction to Next Paint teaches how to optimize for smooth, responsive user input.

 

CLS (Cumulative Layout Shift): This measures how much the layout moves as things load. You've probably had times when you're about to click something, and suddenly the page jumps, and you click the wrong thing. On an online shop, if a product image loads late and pushes everything down, it can cause a layout shift; this score tells us how often that thing happens. The less the page moves, the better. A good score is under 0.1. For a detailed look at how to prevent layout instability caused by images, fonts, and ads, the Cumulative Layout Shift article from web.dev offers practical, actionable strategies.

Other Important Performance Metrics

FCP (First Contentful Paint): This is how quickly you see the first thing appear on the page, like text or an image, after you open a website. The site feels quick if it shows up fast (under 1.8 seconds). Think of it as the moment you know the page is loading.

 

TTFB (Time to First Byte): This is how long it takes for the website to send you something after you ask for it. The site feels snappy if it's fast (under 0.8 seconds). Imagine ringing a doorbell and timing how quickly someone answers, you want a quick response!

 

These Core Web Vitals directly impact Google's SEO ranking algorithm. Pages with poor scores are likely to rank lower in search results, even if the content is high-quality.

Lab Data vs Field Data

We look at both Lab and Field Data when measuring web performance. Tools like Contentsquare provide Lab Data through controlled, simulated tests, which are helpful for development but not enough for real-world data. More importantly, Field Data from Vercel Analytics shows how real users experience your site "in the wild" across different devices and network conditions, making it the key metric for optimization.

core web vitals metrics

Choosing the Right Rendering Strategy in Next.js

Selecting the optimal rendering strategy is crucial for building a high-performance, scalable eCommerce site with Next.js. The framework offers several approaches, each suited to different scenarios and business needs.
 

You can read more about the different rendering strategies in the Next.js Rendering Strategies documentation, which details the different strategies and when to use them.

Server Components

The default rendering method in Next.js is Server Components. This approach renders content on the server, sending the resulting HTML to the client. This is particularly effective for content-heavy pages that do not require much client-side interactivity, ensuring fast load times and strong SEO performance.

Static Rendering

Static Rendering is a powerful option for pages where content does not change frequently. Pages are pre-rendered at build time, resulting in extremely fast load times for users. However, this approach can be less flexible when it comes to updating content in real time.

 

Dynamic Rendering

In contrast, Dynamic Rendering generates HTML on the server for every request. This strategy is ideal for pages that need to display real-time or frequently updated data, such as inventory levels or personalized recommendations.

 

Client-side Rendering

Some parts of your application may require rich interactivity that is not SEO-critical. In these cases, **Client-side Rendering** allows components to be rendered directly in the browser, providing a highly interactive user experience without impacting server performance.

 

Streaming

Streaming enables the server to progressively send UI updates to the client as they become available. This can significantly improve initial load times and perceived performance, especially for complex or data-heavy pages.

You can read more about the different rendering strategies in the Next.js Rendering Strategies documentation, which details the trade-offs between static, dynamic, and server components.

Our Approach: Static Rendering with Revalidation

For our product pages, we chose to implement Static Rendering with Revalidation. This approach allowed us to pre-render static content for speed, while still ensuring that updates, such as price changes or inventory status, could be reflected on the site within a short window. 
We further optimized data fetching by leveraging React's cache and the fetch API, which helped us avoid render-blocking and minimize delays during page loads.

```javascript
import ProductCard from '@/components/ProductCard';
import { revalidatePath } from 'next/cache';

export const revalidate = 60; // Revalidate this page every 60 seconds
async function getProducts() {
  const res = await fetch('https://api.example.com/products', { next: { revalidate: 60 } });
  if (!res.ok) throw new Error('Failed to fetch products');
  return res.json();
}

export default async function ProductsPage() {
  const products = await getProducts();

  return products.map((product) => <ProductCard key={product.id} product={product} />);
}
```

By carefully selecting and combining these rendering strategies, we delivered a fast, reliable, and SEO-friendly experience for our users while maintaining the flexibility needed for a dynamic e-commerce platform.

Reducing JavaScript and Render-Blocking Resources

Modern web applications often ship large amounts of JavaScript, slowing down page loads and negatively impacting Core Web Vitals. To optimize performance and SEO, minimizing and managing JavaScript and other render-blocking resources is crucial. Here are the key strategies we focused on:

Code Splitting

We divided our JavaScript into smaller, more manageable chunks. This ensures that users only download the code they need for the current page, reducing initial load times and improving metrics like First Contentful Paint (FCP).

Next.js provides automatic code splitting at the page level, meaning each page only loads the JavaScript needed for that page:

```javascript
// This component will only be loaded when the /products page is visited
// pages/products.js
export default function Products() {
  return <div>Products Page Content</div>;
}
```

Lazy Loading

Non-critical components and images are loaded only when they enter the viewport or are needed. This reduces the amount of JavaScript and resources loaded upfront, helping improve Largest Contentful Paint (LCP).

```javascript
// React's native lazy loading
const LazyComponent = React.lazy(() => import('../components/HeavyComponent'));

// Next.js dynamic imports (with additional options)
const DynamicComponent = dynamic(() => import('../components/ProductList'), {
  loading: () => <p>Loading...</p>,
});
```

Dynamic Imports & React Suspense

By using dynamic imports and React Suspense, we defer loading heavy or non-essential components until the main content is visible. This approach improves Time to Interactive (TTI) and Interaction to Next Paint (INP), making the site feel faster and more responsive.

```javascript
import dynamic from 'next/dynamic';

// Lazy loading a component
const ProductList = dynamic(() => import('../components/ProductList'), {
  ssr: false, // Disable server-side rendering for this component
});

// Using React Suspense to defer loading of a component
export default function HomePage() {
  return (
    <React.Suspense fallback={<div>Loading...</div>}>
      <ProductList />
    </React.Suspense>
  );
}
```

Minimizing Third-Party Scripts

We audited and removed unnecessary third-party scripts, which are often a significant source of render-blocking resources. Only essential analytics and integrations were kept, and scripts were loaded asynchronously wherever possible.

Fonts and critical CSS were preloaded or inlined to ensure that text and layout appear quickly, reducing layout shifts and improving Cumulative Layout Shift (CLS).

```javascript
// Optimize script loading with next/script
import Script from 'next/script';

// Load after page becomes interactive (default)
<Script src="https://example.com/analytics.js" strategy="afterInteractive" />

// Load during idle time
<Script src="https://example.com/widget.js" strategy="lazyOnload" />
```

Optimizing Fonts and Critical CSS

Fonts and critical CSS were preloaded or inlined to ensure that text and layout appear quickly, reducing layout shifts and improving Cumulative Layout Shift (CLS).

```javascript
// Optimize font loading with next/font
import { Inter } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
});
```

By systematically applying these techniques, we significantly reduced the amount of JavaScript and render-blocking resources, resulting in faster load times and a smoother user experience. Also, the Next.js package bundling guide identifies shared dependencies and optimizes bundles across routes.

API Performance Optimization & Cross-Team Collaboration

Fast, efficient APIs are foundational to high-performing eCommerce experiences. In enterprise-scale applications, slow API responses can bottleneck critical pages, hurt LCP, delay user interactions (INP), and ultimately impact conversions. Optimizing API communication requires not only the right tools, but also tight coordination between frontend and backend teams.

Why We Chose GraphQL for Our API Layer

We adopted GraphQL as our API layer to improve flexibility and performance. Unlike REST, which often returns entire payloads regardless of context, GraphQL lets the client specify exactly what data it needs. This minimizes over-fetching, reduces payload sizes, and shortens response times, which is especially useful when rendering product detail pages or handling large, nested data structures.

Here’s an example of how a GraphQL query helps us request only the essential fields:

```javascript
// Optimized GraphQL query for a product details page
const PRODUCT_QUERY = gql`
  query ProductDetails($id: ID!) {
    product(id: $id) {
      id
      name
      price
      ... on ConfigurableProduct {
        variants {
          id
          price
        }
      }
    }
  }
`;
```

This targeted querying helps streamline rendering and keeps the frontend lean, reducing LCP and INP impact from bloated API responses.

Apollo’s guide to performance optimization offers smart techniques like optimistic UI, caching, and request batching to improve perceived speed in GraphQL-powered apps.

Frontend Strategies for Efficient API Usage

Optimizing how we fetch and manage API data on the frontend was equally critical. This ensured that even when data is delivered quickly, it’s also consumed efficiently.

 

Smart Caching with SWR

We used SWR for client-side data caching to prevent unnecessary requests and ensure fresh, fast data with minimal overhead.

 

Concurrent Data Fetching

For pages that depend on multiple APIs, we leveraged Promise.all to run requests in parallel. This reduced total wait time during page load and hydration.

 

Resilient Error Handling with Retry Logic

We added exponential backoff for retries on failed requests to improve fault tolerance. This allowed the app to recover from temporary network issues without freezing or crashing.

 

Close collaboration with backend teams allowed us to implement GraphQL schemas that are aligned tightly with frontend needs. This eliminated guesswork, enabled schema validation, and supported a rapid development workflow, essential for a performant and scalable eCommerce platform.
 

```javascript
// Example of efficient data fetching with SWR
const { data, error } = useSWR('/api/products', fetcher, {
  revalidateOnFocus: false,
  dedupingInterval: 60000,
  onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
    if (retryCount >= 3) return;
    setTimeout(() => revalidate(), 2 ** retryCount * 1000);
  },
});
```

Monitoring & Continuous Performance Optimization

Performance optimization is an ongoing process. We used Vercel Analytics to track performance metrics and monitor real-world data.

 

To ensure that no new changes negatively impacted performance, we leveraged @next/bundle-analyzer. This tool generates a detailed bundle report on every Pull Request (PR), allowing us to catch any performance regressions before they are deployed to production. This process helps us monitor bundle sizes and detect any unnecessary bloat that could impact load times and performance.

 

By setting up CI/CD pipelines, we automated performance checks and ensured that every deployment passed performance thresholds before going live.

 

Here's a comparison of bundle analysis reports from two different PRs:

Good PR Bundle Analysis showing optimized chunks and minimal size increase
_PR with bundle size showing no increases_

 

good_pr

Bad PR Bundle Analysis showing large bundle size increases]
_PR with bundle size showing unreasonably significant increase_

bad_pr

Conclusion & Key Takeaways

By focusing on these core optimizations, strategic rendering, image handling, caching, minimizing JavaScript, and continuous monitoring, we achieved a perfect Speed Insights score on Vercel. This significantly improved SEO rankings, user experience, and conversions.

 

res_spike

As demonstrated in this article, performance is not just a technical requirement, it's an essential component of a successful eCommerce strategy. If you're building an enterprise-level eCommerce store with Next.js and Vercel, focusing on speed and SEO will pay off in the long run.

 

References

1. Google Web Vitals & PageSpeed Insights
2. Optimize Largest Contentful Paint
3. Interaction to Next Paint
4. Cumulative Layout Shift
5. Server Components
6. Rendering
7. Package Bundling
8. Optimistic UI
9. Vercel Edge Network & Performance
10. Next.js Bundle Analyzer

Share on:

Want to stay on top of everything?

Get updates on industry developments and the software solutions we can now create for a smooth digital transformation.

* I read and understood the ASSIST Software website's terms of use and privacy policy.

Frequently Asked Questions

1. What is ASSIST Software's development process?  

The Software Development Life Cycle (SDLC) we employ defines the following stages for a software project. Our SDLC phases include planning, requirement gathering, product design, development, testing, deployment, and maintenance.

2. What software development methodology does ASSIST Software use?  

ASSIST Software primarily leverages Agile principles for flexibility and adaptability. This means we break down projects into smaller, manageable sprints, allowing continuous feedback and iteration throughout the development cycle. We also incorporate elements from other methodologies to increase efficiency as needed. For example, we use Scrum for project roles and collaboration, and Kanban boards to see workflow and manage tasks. As per the Waterfall approach, we emphasize precise planning and documentation during the initial stages.

3. I'm considering a custom application. Should I focus on a desktop, mobile or web app?  

We can offer software consultancy services to determine the type of software you need based on your specific requirements. Please explore what type of app development would suit your custom build product.   

  • A web application runs on a web browser and is accessible from any device with an internet connection. (e.g., online store, social media platform)   
  • Mobile app developers design applications mainly for smartphones and tablets, such as games and productivity tools. However, they can be extended to other devices, such as smartwatches.    
  • Desktop applications are installed directly on a computer (e.g., photo editing software, word processors).   
  • Enterprise software manages complex business functions within an organization (e.g., Customer Relationship Management (CRM), Enterprise Resource Planning (ERP)).

4. My software product is complex. Are you familiar with the Scaled Agile methodology?

We have been in the software engineering industry for 30 years. During this time, we have worked on bespoke software that needed creative thinking, innovation, and customized solutions. 

Scaled Agile refers to frameworks and practices that help large organizations adopt Agile methodologies. Traditional Agile is designed for small, self-organizing teams. Scaled Agile addresses the challenges of implementing Agile across multiple teams working on complex projects.  

SAFe provides a structured approach for aligning teams, coordinating work, and delivering value at scale. It focuses on collaboration, communication, and continuous delivery for optimal custom software development services. 

5. How do I choose the best collaboration model with ASSIST Software?  

We offer flexible models. Think about your project and see which models would be right for you.   

  • Dedicated Team: Ideal for complex, long-term projects requiring high continuity and collaboration.   
  • Team Augmentation: Perfect for short-term projects or existing teams needing additional expertise.   
  • Project-Based Model: Best for well-defined projects with clear deliverables and a fixed budget.   

Contact us to discuss the advantages and disadvantages of each model. 

ASSIST Software Team Members

See the past, present and future of tech through the eyes of an experienced Romanian custom software company. The ASSIST Insider newsletter highlights your path to digital transformation.

* I read and understood the ASSIST Software website's terms of use and privacy policy.

Follow us

© 2025 ASSIST Software. All rights reserved. Designed with love.