supaguardsupaguardDocs
Playwright

Playwright Monitoring Tutorial: Build Reliable Synthetic Checks

Step-by-step Playwright monitoring tutorial for production-ready synthetic checks, including selectors, retries, alerts, and CI workflows.

This tutorial walks you from zero to a production-ready Playwright synthetic monitor.

You'll build one robust check, make it less flaky, and connect it to actionable alerts.

Prerequisites

  • A deployed app URL (staging or production)
  • A synthetic test account
  • Node.js and Playwright basics

Step 1: Start with one business-critical journey

Choose one flow with direct business impact, such as login.

import { test, expect } from "@playwright/test";

test("user can login and open dashboard", async ({ page }) => {
  await page.goto("https://app.example.com/login");
  await page.getByLabel("Email").fill(process.env.SYNTHETIC_EMAIL!);
  await page.getByLabel("Password").fill(process.env.SYNTHETIC_PASSWORD!);
  await page.getByRole("button", { name: "Sign in" }).click();

  await expect(page).toHaveURL(/.*dashboard/);
  await expect(page.getByText("Welcome back")).toBeVisible();
});

Step 2: Use stable selectors

Prefer semantic locators:

  • getByRole
  • getByLabel
  • getByTestId (for custom controls)

Avoid brittle CSS selectors tied to layout classes.

Step 3: Add reliability guards

Production monitors must tolerate normal variance.

test("dashboard renders key widgets", async ({ page }) => {
  await page.goto("https://app.example.com/dashboard", {
    waitUntil: "domcontentloaded",
  });

  await expect(page.getByRole("heading", { name: /dashboard/i })).toBeVisible();
  await expect(page.getByTestId("revenue-widget")).toBeVisible({ timeout: 20_000 });
});

Tips:

  • Set explicit timeouts for slow but acceptable elements
  • Assert only what matters for user success
  • Keep each monitor focused and readable

Step 4: Capture debugging evidence

When checks fail, screenshots and traces reduce MTTR.

import { test } from "@playwright/test";

test("checkout flow", async ({ page }) => {
  // ... test steps
  await page.screenshot({ path: "artifacts/checkout.png", fullPage: true });
});

Step 5: Configure retries intentionally

Use retries to reduce false positives, not to hide real incidents.

  • Retry once for known transient network issues
  • Alert immediately if a critical check fails repeatedly
  • Track first-failure rate to identify growing instability

Step 6: Connect checks to alerting

Route alerts based on severity:

  • Critical: login/checkout failures → on-call notification
  • High: dashboard/core action degradation → team Slack
  • Medium: non-critical settings flow failures → issue backlog

Step 7: Schedule with business context

Recommended schedule:

  • Every 5 min: login, signup, checkout
  • Every 15 min: onboarding and key settings flows
  • Hourly: broader end-to-end journeys

Step 8: Add to CI and release gates

Run synthetic tests in CI against preview environments to block regressions before deploy.

npx playwright test tests/synthetic/login.spec.ts

Then run the same scripts in your monitoring platform after deployment.

Step 9: Keep test data healthy

  • Use dedicated synthetic users
  • Reset state between runs when needed
  • Rotate credentials and API keys regularly

Step 10: Expand coverage gradually

After login is stable, add:

  1. Signup
  2. Upgrade/checkout
  3. Primary in-app action
  4. Third-party integration touchpoints

On this page