Skip to content
Back to skills

Synthetic Monitoring

ASecurity

Implement synthetic monitoring and automated testing to simulate user behavior and detect issues before users. Use when creating end-to-end test scenarios, monitoring API flows, or validating user workflows.

  • 327 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added February 7, 2026
testingjavascriptgojavanodetestingapiperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add aj-geddes/useful-ai-prompts --skill synthetic-monitoring --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Synthetic Monitoring?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Synthetic Monitoring
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/aj-geddes-synthetic-monitoring/badge)](https://www.skillsdirectory.com/skills/aj-geddes-synthetic-monitoring)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: synthetic-monitoring
description: Implement synthetic monitoring and automated testing to simulate user behavior and detect issues before users. Use when creating end-to-end test scenarios, monitoring API flows, or validating user workflows.
---

# Synthetic Monitoring

## Overview

Set up synthetic monitoring to automatically simulate real user journeys, API workflows, and critical business transactions to detect issues and validate performance.

## When to Use

- End-to-end workflow validation
- API flow testing
- User journey simulation
- Transaction monitoring
- Critical path validation

## Instructions

### 1. **Synthetic Tests with Playwright**

```javascript
// synthetic-tests.js
const { chromium } = require('playwright');

class SyntheticMonitor {
  constructor(config = {}) {
    this.baseUrl = config.baseUrl || 'https://app.example.com';
    this.timeout = config.timeout || 30000;
  }

  async testUserFlow() {
    const browser = await chromium.launch();
    const page = await browser.newPage();
    const metrics = { steps: {} };
    const startTime = Date.now();

    try {
      // Step 1: Navigate to login
      let stepStart = Date.now();
      await page.goto(`${this.baseUrl}/login`, { waitUntil: 'networkidle' });
      metrics.steps.navigation = Date.now() - stepStart;

      // Step 2: Perform login
      stepStart = Date.now();
      await page.fill('input[name="email"]', 'test@example.com');
      await page.fill('input[name="password"]', 'password123');
      await page.click('button[type="submit"]');
      await page.waitForNavigation({ waitUntil: 'networkidle' });
      metrics.steps.login = Date.now() - stepStart;

      // Step 3: Navigate to dashboard
      stepStart = Date.now();
      await page.goto(`${this.baseUrl}/dashboard`, { waitUntil: 'networkidle' });
      metrics.steps.dashboard = Date.now() - stepStart;

      // Step 4: Search for products
      stepStart = Date.now();
      await page.fill('input[placeholder="Search products"]', 'laptop');
      await page.waitForSelector('.product-list');
      metrics.steps.search = Date.now() - stepStart;

      // Step 5: Add to cart
      stepStart = Date.now();
      const firstProduct = await page.$('.product-item');
      if (firstProduct) {
        await firstProduct.click();
        await page.click('button:has-text("Add to Cart")');
        await page.waitForSelector('[data-testid="cart-count"]');
      }
      metrics.steps.addToCart = Date.now() - stepStart;

      metrics.totalTime = Date.now() - startTime;
      metrics.status = 'success';
    } catch (error) {
      metrics.status = 'failed';
      metrics.error = error.message;
      metrics.totalTime = Date.now() - startTime;
    } finally {
      await browser.close();
    }

    return metrics;
  }

  async testMobileUserFlow() {
    const browser = await chromium.launch();
    const context = await browser.createBrowserContext({
      ...chromium.devices['iPhone 12']
    });
    const page = await context.newPage();

    try {
      const metrics = { device: 'iPhone 12', steps: {} };
      const startTime = Date.now();

      let stepStart = Date.now();
      await page.goto(this.baseUrl, { waitUntil: 'networkidle' });
      metrics.steps.navigation = Date.now() - stepStart;

      const viewport = page.viewportSize();
      metrics.viewport = viewport;

      stepStart = Date.now();
      await page.click('.menu-toggle');
      await page.waitForSelector('.mobile-menu.open');
      metrics.steps.mobileInteraction = Date.now() - stepStart;

      metrics.totalTime = Date.now() - startTime;
      metrics.status = 'success';

      return metrics;
    } catch (error) {
      return { status: 'failed', error: error.message, device: 'iPhone 12' };
    } finally {
      await browser.close();
    }
  }

  async testWithPerformanceMetrics() {
    const browser = await chromium.launch();
    const page = await browser.newPage();

    try {
      await page.goto(this.baseUrl, { waitUntil: 'networkidle' });

      const perfMetrics = JSON.parse(
        await page.evaluate(() => JSON.stringify(window.performance.timing))
      );

      const metrics = {
        navigationTiming: {
          domInteractive: perfMetrics.domInteractive - perfMetrics.navigationStart,
          domComplete: perfMetrics.domComplete - perfMetrics.navigationStart,
          loadComplete: perfMetrics.loadEventEnd - perfMetrics.navigationStart
        },
        status: 'success'
      };

      return metrics;
    } catch (error) {
      return { status: 'failed', error: error.message };
    } finally {
      await browser.close();
    }
  }

  async recordMetrics(testName, metrics) {
    try {
      await axios.post('http://monitoring-service/synthetic-results', {
        testName,
        timestamp: new Date(),
        metrics,
        passed: metrics.status === 'success'
      });
    } catch (error) {
      console.error('Failed to record metrics:', error);
    }
  }
}

module.exports = SyntheticMonitor;
```

### 2. **API Synthetic Tests**

```javascript
// api-synthetic-tests.js
const axios = require('axios');

class APISyntheticTests {
  constructor(config = {}) {
    this.baseUrl = config.baseUrl || 'https://api.example.com';
    this.client = axios.create({ baseURL: this.baseUrl });
  }

  async testAuthenticationFlow() {
    const results = { steps: {}, status: 'success' };

    try {
      const registerStart = Date.now();
      const registerRes = await this.client.post('/auth/register', {
        email: `test-${Date.now()}@example.com`,
        password: 'Test@123456'
      });
      results.steps.register = Date.now() - registerStart;

      if (registerRes.status !== 201) throw new Error('Registration failed');

      const loginStart = Date.now();
      const loginRes = await this.client.post('/auth/login', {
        email: registerRes.data.email,
        password: 'Test@123456'
      });
      results.steps.login = Date.now() - loginStart;

      const token = loginRes.data.token;

      const authStart = Date.now();
      await this.client.get('/api/profile', {
        headers: { Authorization: `Bearer ${token}` }
      });
      results.steps.authenticatedRequest = Date.now() - authStart;

      const logoutStart = Date.now();
      await this.client.post('/auth/logout', {}, {
        headers: { Authorization: `Bearer ${token}` }
      });
      results.steps.logout = Date.now() - logoutStart;

      return results;
    } catch (error) {
      results.status = 'failed';
      results.error = error.message;
      return results;
    }
  }

  async testTransactionFlow() {
    const results = { steps: {}, status: 'success' };

    try {
      const orderStart = Date.now();
      const orderRes = await this.client.post('/api/orders', {
        items: [{ sku: 'ITEM-001', quantity: 2 }]
      }, {
        headers: { 'X-Idempotency-Key': `order-${Date.now()}` }
      });
      results.steps.createOrder = Date.now() - orderStart;

      const getStart = Date.now();
      const getRes = await this.client.get(`/api/orders/${orderRes.data.id}`);
      results.steps.getOrder = Date.now() - getStart;

      const paymentStart = Date.now();
      await this.client.post(`/api/orders/${orderRes.data.id}/payment`, {
        method: 'credit_card',
        amount: getRes.data.total
      });
      results.steps.processPayment = Date.now() - paymentStart;

      return results;
    } catch (error) {
      results.status = 'failed';
      results.error = error.message;
      return results;
    }
  }

  async testUnderLoad(concurrentUsers = 10, duration = 60000) {
    const startTime = Date.now();
    const results = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      averageResponseTime: 0,
      p95ResponseTime: 0
    };

    const responseTimes = [];

    const makeRequest = async () => {
      const reqStart = Date.now();
      try {
        await this.client.get('/api/health');
        results.successfulRequests++;
        responseTimes.push(Date.now() - reqStart);
      } catch {
        results.failedRequests++;
      }
      results.totalRequests++;
    };

    const userSimulations = Array(concurrentUsers).fill(null).map(async () => {
      while (Date.now() - startTime < duration) {
        await makeRequest();
        await new Promise(r => setTimeout(r, Math.random() * 1000));
      }
    });

    await Promise.all(userSimulations);

    responseTimes.sort((a, b) => a - b);
    results.averageResponseTime =
      responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length;
    results.p95ResponseTime =
      responseTimes[Math.floor(responseTimes.length * 0.95)];

    return results;
  }
}

module.exports = APISyntheticTests;
```

### 3. **Scheduled Synthetic Monitoring**

```javascript
// scheduled-monitor.js
const cron = require('node-cron');
const SyntheticMonitor = require('./synthetic-tests');
const APISyntheticTests = require('./api-synthetic-tests');
const axios = require('axios');

class ScheduledSyntheticMonitor {
  constructor(config = {}) {
    this.eMonitor = new SyntheticMonitor(config);
    this.apiTests = new APISyntheticTests(config);
    this.alertThreshold = config.alertThreshold || 5000;
  }

  start() {
    cron.schedule('*/5 * * * *', () => this.runE2ETests());
    cron.schedule('*/2 * * * *', () => this.runAPITests());
    cron.schedule('0 * * * *', () => this.runLoadTest());
  }

  async runE2ETests() {
    try {
      const metrics = await this.eMonitor.testUserFlow();
      await this.recordResults('e2e-user-flow', metrics);

      if (metrics.totalTime > this.alertThreshold) {
        await this.sendAlert('e2e-user-flow', metrics);
      }
    } catch (error) {
      console.error('E2E test failed:', error);
    }
  }

  async runAPITests() {
    try {
      const authMetrics = await this.apiTests.testAuthenticationFlow();
      const transactionMetrics = await this.apiTests.testTransactionFlow();

      await this.recordResults('api-auth-flow', authMetrics);
      await this.recordResults('api-transaction-flow', transactionMetrics);

      if (authMetrics.status === 'failed' || transactionMetrics.status === 'failed') {
        await this.sendAlert('api-tests', { authMetrics, transactionMetrics });
      }
    } catch (error) {
      console.error('API test failed:', error);
    }
  }

  async runLoadTest() {
    try {
      const results = await this.apiTests.testUnderLoad(10, 30000);
      await this.recordResults('load-test', results);

      if (results.failedRequests > 0) {
        await this.sendAlert('load-test', results);
      }
    } catch (error) {
      console.error('Load test failed:', error);
    }
  }

  async recordResults(testName, metrics) {
    try {
      await axios.post('http://monitoring-service/synthetic-results', {
        testName,
        timestamp: new Date(),
        metrics
      });
      console.log(`Recorded: ${testName}`, metrics);
    } catch (error) {
      console.error('Failed to record results:', error);
    }
  }

  async sendAlert(testName, metrics) {
    try {
      await axios.post('http://alerting-service/alerts', {
        type: 'synthetic_monitoring',
        testName,
        severity: 'warning',
        message: `Synthetic test '${testName}' has issues`,
        metrics,
        timestamp: new Date()
      });
      console.log(`Alert sent for ${testName}`);
    } catch (error) {
      console.error('Failed to send alert:', error);
    }
  }
}

module.exports = ScheduledSyntheticMonitor;
```

## Best Practices

### ✅ DO
- Test critical user journeys
- Simulate real browser conditions
- Monitor from multiple locations
- Track response times
- Alert on test failures
- Rotate test data
- Test mobile and desktop
- Include error scenarios

### ❌ DON'T
- Test with production data
- Reuse test accounts
- Skip timeout configurations
- Ignore test maintenance
- Test too frequently
- Hard-code credentials
- Ignore geographic variations
- Test only happy paths

## Key Metrics

- Response time
- Success rate
- Availability
- Core Web Vitals
- Error rate

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.