Tutorial · performance · Published 2026-08-16 · 3 min read

Adding Lighthouse CI to your pipeline

Lighthouse CI catches performance and Core Web Vitals regressions before merge. Set budgets and assertions, then run them in GitHub Actions.

Why lab testing in CI helps

A performance regression is easiest to catch at the moment it is introduced, before it reaches real users. Lighthouse CI (lhci) runs automated Lighthouse audits on pull requests and lets a failing budget block the merge. It is the same lab measurement that powers a web performance audit and PageSpeed Insights, but automated and enforced rather than run by hand. The main caveat is that a single synthetic run in CI is noisy and environment-dependent, so it is best at catching hard regressions and trends, not at proving perfect field performance; pair it with field data for the real picture.

Define a budget first

A performance budget is the guardrail. Create a budget.json that caps page weight and resources so a blowout fails the check:

[
  {
    "path": "/*",
    "resourceSizes": [
      { "resourceType": "total", "budget": 250 },
      { "resourceType": "script", "budget": 140 }
    ],
    "resourceCounts": [
      { "resourceType": "third-party", "budget": 12 }
    ]
  }
]

Path budget of /* applies it to every page. Tune the numbers to your real baseline; an overly strict budget fails every build, and an overly loose one catches nothing. Set thresholds from your worst known-good page, not from an ideal you have never met.

Configure assertions

Beyond raw byte budgets, lighthouserc.json controls which audits must pass and at what level. Assertions gate on metric scores and numeric values:

{
  "ci": {
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.9 }],
        "largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
        "total-blocking-time": ["warn", { "maxNumericValue": 200 }]
      }
    }
  }
}

An error level fails the run; warn is informational. Use error for the metrics you will genuinely block on, such as a poor performance score or an LCP over the 2.5-second threshold, and keep warn for things you are still tuning. This is the same threshold language used in the LCP/INP/CLS audit procedure, so you can carry your audit findings straight into the assertion file.

Gate the pull request

Wire it into GitHub Actions so the budget runs on every pull request:

- uses: treosh/lighthouse-ci-action@v12
  with:
    urls: |
      https://staging.example.com/
    budgetPath: ./budget.json

When a URL exceeds a budget or an audit assertion fails, the action returns a non-zero exit code and the check fails, and branch protection can require it before merge. The page under test must be reachable, so either deploy a preview or serve a local build in the same job. Because a single run is noisy, prefer asserting on stable things such as page weight and static audits, and treat a metric-based score as a trend line rather than an exact measurement.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services