Scheduling
Run flows on a cron schedule to continuously validate your services, detect regressions early, and monitor production systems around the clock.
TestMesh includes a built-in scheduler that executes flows automatically on a cron schedule. Scheduled runs are stored with full execution history so you can track trends, spot regressions, and get notified on failures.
How Scheduling Works
The scheduler is powered by Redis Streams for reliable job queuing. When a scheduled time arrives:
The scheduler enqueues a job into Redis Streams.
A worker picks up the job and executes the flow.
Results are stored in the executions table with the schedule ID attached.
Notifications are sent if the execution fails (configured per schedule).
Creating Schedules
Via the Dashboard
Navigate to Schedules in the dashboard sidebar and click New Schedule. Configure:
- Flow — Select the flow to run
- Cron expression — When to run it
- Environment — Which environment variables to use
- Notifications — Slack, email, or webhook on failure
Via the API
curl -X POST http://localhost:5016/api/v1/workspaces/{workspace_id}/schedules \
-H "Content-Type: application/json" \
-d '{
"name": "Hourly Health Check",
"flow_id": "flow-uuid-here",
"cron": "0 * * * *",
"environment_id": "env-uuid-here",
"enabled": true
}'Cron Expression Format
TestMesh uses standard 5-field cron syntax:
┌───── minute (0–59)
│ ┌───── hour (0–23)
│ │ ┌───── day of month (1–31)
│ │ │ ┌───── month (1–12)
│ │ │ │ ┌───── day of week (0–6, Sunday=0)
│ │ │ │ │
* * * * *Common Schedules
| Expression | Meaning |
|---|---|
* * * * * | Every minute |
0 * * * * | Every hour |
0 9 * * 1-5 | Weekdays at 9:00 AM |
0 */4 * * * | Every 4 hours |
30 8 * * * | Daily at 8:30 AM |
0 0 * * 0 | Weekly on Sunday at midnight |
0 0 1 * * | Monthly on the 1st at midnight |
Use crontab.guru to validate and preview cron expressions before saving a schedule.
Example: Production Health Monitoring
Schedule a health-check flow to run every 5 minutes and alert on failure:
flow:
name: "Production Health Check"
description: "Verify all services are responding correctly"
steps:
- id: check_user_service
action: http_request
config:
method: GET
url: "${USER_SERVICE_URL}/health"
timeout: 5s
assert:
- status == 200
- response.body.status == "ok"
- id: check_order_service
action: http_request
config:
method: GET
url: "${ORDER_SERVICE_URL}/health"
timeout: 5s
assert:
- status == 200
- id: check_database
action: database_query
config:
query: "SELECT 1"
assert:
- result.count == 1
- id: check_kafka
action: kafka_produce
config:
brokers: ["${KAFKA_BROKERS}"]
topic: "health.checks"
value:
timestamp: "${TIMESTAMP}"
source: "testmesh"Configure the schedule:
{
"name": "Production Health Check (every 5 min)",
"flow_id": "health-check-flow-id",
"cron": "*/5 * * * *",
"environment_id": "production-env-id",
"enabled": true,
"on_failure": {
"slack_webhook": "${SLACK_WEBHOOK_URL}",
"notify": true
}
}Execution History
Every scheduled run creates an execution record visible in the dashboard. The Schedules view shows:
- Next scheduled run time
- Last run status (pass / fail)
- Pass rate over the last 30 days
- Average duration trend
Drill into any scheduled execution to see full step-level detail, logs, and request/response inspection — identical to manually triggered executions.
Enable and Disable Schedules
Schedules can be toggled without deleting them — useful when deploying a change and temporarily pausing a schedule:
# Disable a schedule
curl -X PATCH http://localhost:5016/api/v1/schedules/{schedule_id} \
-d '{"enabled": false}'
# Re-enable it
curl -X PATCH http://localhost:5016/api/v1/schedules/{schedule_id} \
-d '{"enabled": true}'In the dashboard, use the toggle switch on each schedule row.
Time Zone Support
Schedules run in UTC by default. Specify a time zone to schedule relative to local business hours:
{
"name": "Business Hours Report",
"cron": "0 9 * * 1-5",
"timezone": "America/New_York"
}All supported IANA time zone names are accepted.
Notifications on Failure
Configure failure notifications per schedule:
{
"on_failure": {
"slack_webhook": "${SLACK_WEBHOOK_URL}",
"notify": true
}
}The Slack message includes the flow name, which step failed, the error message, and a direct link to the execution detail page.
{
"on_failure": {
"email": {
"to": ["team@example.com"],
"notify": true
}
}
}{
"on_failure": {
"webhook": {
"url": "https://your-system.example.com/alerts",
"method": "POST",
"headers": {
"Authorization": "Bearer ${WEBHOOK_TOKEN}"
}
}
}
}Concurrent Execution Control
By default, if a scheduled execution is still running when the next one is due, the new run is skipped (no stacking). Configure this behavior:
{
"name": "Long-Running Suite",
"cron": "0 * * * *",
"concurrent_policy": "skip" // "skip" (default) or "allow"
}Use "allow" only for fast flows where overlap is intentional, such as load simulations.
Using Environments with Schedules
Attach an environment to a schedule to run the same flow with different configuration in different contexts:
// Run the same health-check flow against staging and production
[
{
"name": "Staging Health Check",
"flow_id": "health-check-id",
"cron": "*/10 * * * *",
"environment_id": "staging-environment-id"
},
{
"name": "Production Health Check",
"flow_id": "health-check-id",
"cron": "*/5 * * * *",
"environment_id": "production-environment-id"
}
]See the Environments documentation for how to define environment variable sets.
Telemetry & Trace Intelligence
Ingest OpenTelemetry traces, auto-discover flows, detect drift, validate traces against expected paths, and get AI-powered root cause analysis.
Reporting
Generate HTML, JUnit XML, and JSON reports with trend analysis, flaky test detection, Slack notifications, and CI/CD integration.