Lighthouse scores drift as you add features and dependencies. A site that scored 95 on performance six months ago might drop to 75 after adding analytics, a chat widget, and a few unoptimized images. Running Lighthouse in CI on every pull request catches these regressions before they reach production.
What is Lighthouse CI?
Lighthouse CI is the official way to run Lighthouse audits in a pipeline. It handles browser automation, runs audits against one or more URLs, aggregates results from multiple runs, and asserts on scores or metrics. If a score drops below your threshold, the build fails or emits a warning.
| Feature | Description |
|---|---|
| Multiple runs | Runs audits 3-5 times and takes the median to reduce noise |
| Assertions | Fail builds if performance < 80 or LCP > 2.5s |
| Report storage | Upload reports to LHCI server or temporary storage |
| CI integration | Works with GitHub Actions, GitLab CI, CircleCI, Jenkins |
| Budget support | Set budgets for metrics, resource sizes, or request counts |
Lighthouse CI is not a replacement for manual audits or real user monitoring. It is a guardrail that catches obvious regressions in a controlled environment before code ships.
Installation and basic setup
Install Lighthouse CI as a dev dependency and create a configuration file.
npm install -D @lhci/cli
Create lighthouserc.js at the project root:
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000/', 'http://localhost:3000/about'],
numberOfRuns: 3,
startServerCommand: 'npm run start',
},
assert: {
preset: 'lighthouse:recommended',
assertions: {
'categories:performance': ['error', { minScore: 0.8 }],
'categories:accessibility': ['error', { minScore: 0.9 }],
'largest-contentful-paint': ['warn', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
},
},
upload: {
target: 'temporary-public-storage',
},
},
};
Run with:
npx lhci autorun
The autorun command starts your server, runs Lighthouse against each URL the specified number of times, checks assertions, and uploads reports.
Choosing URLs to test
Test the pages that matter most for user experience and business goals:
| Page type | Why test it |
|---|---|
| Homepage | First impression, often the LCP candidate |
| Key landing pages | Marketing pages where users arrive from search |
| App shell or dashboard | Critical for logged-in users |
| Heavy pages | Pages with lots of images, scripts, or third-party embeds |
Avoid testing every page. Focus on 3-5 representative URLs. Testing more pages increases CI time without proportional benefit. Add pages only when you have specific regressions to catch.
Running in GitHub Actions
Create .github/workflows/lighthouse.yml:
name: Lighthouse CI
on: [pull_request]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- name: Run Lighthouse CI
run: npx lhci autorun
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
For preview deployments (Vercel, Netlify), replace the localhost URLs with the preview URL. Vercel exposes this as VERCEL_URL in the environment. You can pass it to Lighthouse CI:
collect: {
url: [
`https://${process.env.VERCEL_URL}/`,
`https://${process.env.VERCEL_URL}/about`,
],
numberOfRuns: 3,
}
Setting effective thresholds
Start with thresholds you can meet today. The goal is to prevent regressions, not to block all PRs.
| Metric | Good starting threshold | Stretch goal |
|---|---|---|
| Performance score | 80 | 90 |
| Accessibility score | 90 | 100 |
| LCP | 2.5s | 1.5s |
| CLS | 0.1 | 0.05 |
| TBT | 300ms | 150ms |
Tighten thresholds over time. When your site consistently scores 85 on performance, raise the threshold to 85 so any regression triggers a warning.
Reducing flaky results
Lighthouse runs in a simulated environment and results vary. Network conditions, CPU throttling, and server response times all affect scores. To reduce flakiness:
- Run multiple audits: Use
numberOfRuns: 3or5and take the median. - Use consistent environments: Test against preview deployments, not local dev servers with hot reloading.
- Avoid shared CI runners: If possible, use dedicated runners or machines with consistent specs.
- Disable animations: Long animations can affect CLS and LCP measurements.
If a test fails intermittently, check the report to see which metric varied. Metrics like TBT are more sensitive to CPU load than LCP.
Storing and comparing reports
Lighthouse CI can upload reports to temporary public storage (expires after a few days), an LHCI server you host, or Vercel Remote Cache.
To host your own LHCI server:
npm install -g @lhci/server
lhci server --storage.storageMethod=sql --storage.sqlDatabasePath=./lhci.db
In your config:
upload: {
target: 'lhci',
serverBaseUrl: 'https://your-lhci-server.com',
token: process.env.LHCI_TOKEN,
}
The LHCI server provides a dashboard where you can compare scores across branches, view trends over time, and drill into individual reports.
Budget files for granular control
Beyond category scores, you can set budgets for specific resources:
assert: {
budgetsPath: './budgets.json',
}
In budgets.json:
[
{
"path": "/*",
"resourceSizes": [
{ "resourceType": "script", "budget": 200 },
{ "resourceType": "image", "budget": 500 }
],
"resourceCounts": [
{ "resourceType": "third-party", "budget": 5 }
]
}
]
This fails the build if JavaScript exceeds 200KB or if you load more than 5 third-party resources. Budgets are useful for catching dependency bloat.
Integrating with PR comments
Install the Lighthouse CI GitHub App to post score summaries as PR comments. The app compares the PR branch to the base branch and shows score changes.
- Install the app from github.com/apps/lighthouse-ci.
- Add
LHCI_GITHUB_APP_TOKENto your repository secrets. - The app posts comments automatically when Lighthouse CI runs.
PR comments make performance visible to the whole team. A PR that drops performance by 10 points gets immediate feedback.
Common pitfalls
| Pitfall | Solution |
|---|---|
| Testing against dev server | Build and serve production bundle |
| No numberOfRuns | Always run 3-5 times for stability |
| Thresholds too strict | Start lenient, tighten over time |
| Ignoring accessibility | Include a11y assertions, not just performance |
| No report storage | Use LHCI server or temporary storage for debugging |
When Lighthouse CI is not enough
Lighthouse CI tests in a simulated environment with throttled network and CPU. Real users have different devices and connections. Complement Lighthouse CI with:
- Real User Monitoring (RUM): Measure Core Web Vitals from actual visitors.
- A/B testing: Compare performance impact of features.
- Manual audits: Periodically run full Lighthouse audits and review opportunities.
Lighthouse CI catches obvious regressions. RUM tells you how real users experience your site.
Summary
Lighthouse CI integrates performance and accessibility checks into your CI pipeline. Set up a config file, choose thresholds, run audits on PRs, and store reports for comparison. Start with lenient thresholds and tighten them as your site improves. Combine CI checks with real user monitoring for a complete picture of site performance.
