Creating Triggers in Production
This guide explains how to create, manage, and operate triggers in a production TimeTriggers deployment. It covers API usage, authentication, best practices, and troubleshooting for production environments.
Overview
In production, triggers are created by sending HTTP requests to the TimeTriggers API at https://api.timetriggers.io. The process is the same as in development, but with additional considerations around:
- Authentication: Using production API keys securely
- Reliability: Ensuring triggers fire when expected
- Observability: Monitoring trigger status and results
- Quota: Managing your monthly call limits
- Security: Protecting sensitive data in trigger configurations
Prerequisites
Before creating production triggers, ensure you have:
- A production account with TimeTriggers (sign up via the dashboard)
- API keys created in the dashboard for your production project
- Your target endpoint ready to receive the scheduled requests
- Understanding of the API basics
Creating Your First Production Trigger
The simplest way to create a production trigger is using the /schedule endpoint with curl:
curl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "ttr-url: https://your-production-service.com/webhooks/endpoint" \-H "ttr-scheduled-at: 2026-10-17T14:30:00Z" \-H "Content-Type: application/json" \-d '{"event": "reminder", "userId": 12345}'
This schedules a one-shot trigger that will fire at 14:30 UTC on October 17, 2026.
Response
A successful request returns:
{"triggerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890","scheduledAt": "2026-10-17T14:30:00.000Z","operation": "schedule","kind": "job","monthQuotaRemaining": 499}
Production Best Practices
1. Use Custom Keys for Idempotency
Always use ttr-custom-keyheader for triggers you may need to update:
curl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "ttr-url: https://your-service.com/reminders" \-H "ttr-scheduled-at: 2026-10-18T09:00:00Z" \-H "ttr-custom-key: user-12345-daily-reminder" \-H "Content-Type: application/json" \-d '{"userId": 12345}'
This allows you to update the trigger later by sending the same custom key with new parameters:
# Update the trigger timecurl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "ttr-url: https://your-service.com/reminders" \-H "ttr-scheduled-at: 2026-10-19T09:00:00Z" \-H "ttr-custom-key: user-12345-daily-reminder" \-H "Content-Type: application/json" \-d '{"userId": 12345}'
2. Use Tags for Organization and Policies
Tag your triggers to organize them and apply tag policies:
curl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "ttr-url: https://your-service.com/billing" \-H "ttr-scheduled-at: now | add 1h" \-H "ttr-tags: billing,critical,production" \-H "ttr-custom-key: billing-invoice-67890" \-H "Content-Type: application/json" \-d '{"invoiceId": 67890}'
Then create a tag policy for production-critical triggers:
curl -X POST https://api.timetriggers.io/tag-policies \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "Content-Type: application/json" \-d '{"tag": "critical","maxConcurrent": 5,"requestTimeoutSeconds": 60,"retryMaxAttempts": 3,"retryStrategy": "exponential","retryInitialDelaySeconds": 5,"retryMaxDelaySeconds": 60,"retryOn": "5xx+net"}'
3. Use Recurring Triggers for Scheduled Jobs
For jobs that run on a schedule (cron), use recurring triggers:
# Send a daily digest at 8 AM UTCcurl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "ttr-url: https://your-service.com/digests/daily" \-H "ttr-scheduled-at: cron(0 8 * * *)" \-H "ttr-custom-key: daily-digest" \-H "ttr-title: Daily Digest Email" \-H "ttr-tags: digests,production" \-H "Content-Type: application/json"
With a timezone:
# Send at 9 AM Paris time (CEST/ CET)curl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "ttr-url: https://your-service.com/reports/morning" \-H "ttr-scheduled-at: cron(0 9 * * *, Europe/Paris)" \-H "ttr-custom-key: morning-report" \-H "Content-Type: application/json"
See Recurring triggers for full cron syntax.
4. Secure Your API Keys
Never commit API keys to version control. Instead:
- Store them in environment variables or secret managers
- Use different keys for different environments (production, staging, development)
- Rotate keys regularly
- Delete unused keys
Example using environment variables:
export TTR_API_KEY="ttr_your_production_key_here"curl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: $TTR_API_KEY" \-H "ttr-url: https://your-service.com/endpoint" \-H "ttr-scheduled-at: now | add 30m"
5. Monitor Your Triggers
Use the dashboard to:
- View all your triggers and their status
- Check execution history and response codes
- Set up alerts for failures via Slack or email
- Monitor your quota usage
For programmatic monitoring, you can use the dashboard API endpoints (requires session cookie):
# List all triggers (requires dashboard session)curl https://timetriggers.io/api/jobs \-H "Cookie: <your_session_cookie>"
6. Handle Timeouts and Retries
Configure appropriate timeouts and retry policies using tag policies:
# For API calls that may be slowcurl -X POST https://api.timetriggers.io/tag-policies \-H "ttr-api-key: ttr_YOUR_PRODUCTION_API_KEY" \-H "Content-Type: application/json" \-d '{"tag": "slow-api","requestTimeoutSeconds": 120,"retryMaxAttempts": 5,"retryStrategy": "exponential","retryInitialDelaySeconds": 10,"retryMaxDelaySeconds": 300,"retryOn": "5xx+net"}'
See Tag policies for all available options.
Production Deployment Considerations
High Availability
The TimeTriggers production deployment runs multiple API replicas (4 by default) in Kubernetes. Each replica runs all background loops (scheduler, executor, materializer, reaper, alerter) and coordinates through PostgreSQL using row locks and advisory locks.
This means:
- Triggers are reliably executed even if individual pods fail
- The system automatically recovers from pod restarts
- No manual intervention is needed for normal operations
Database Migrations
Production migrations are handled automatically via Helm pre-upgrade hooks. The migration job runs prisma migrate deploy with:
- Backoff limit: 3 retries
- Active deadline: 120 seconds
- Restart policy: Never
If a migration fails, the Helm upgrade is rolled back automatically.
Monitoring and Health Checks
The production API exposes a health endpoint:
curl https://api.timetriggers.io/health
Response:
{"status": "ok", "schedulerStaleMs": 106, "materializerStaleMs": 246}
Kubernetes uses this for both liveness and readiness probes (30s and 10s intervals respectively).
Health check limitations: The health endpoint only checks that the scheduler and materializer loops are running. It does NOT verify:
- The executor loop (triggers may pile up silently)
- Database connectivity (a fresh process reports "ok" for 30-60 seconds)
- Actual trigger firing
For full observability, monitor trigger execution in the dashboard.
Common Production Patterns
1. Delayed Processing
Schedule a trigger to fire after a delay:
# Fire in 1 hourcurl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: $TTR_API_KEY" \-H "ttr-url: https://your-service.com/process" \-H "ttr-scheduled-at: now | add 1h" \-H "ttr-custom-key: user-12345-delayed-process" \-H "Content-Type: application/json" \-d '{"userId": 12345, "action": "process"}'
2. Retry with Exponential Backoff
Create a tag policy with exponential backoff for unreliable endpoints:
curl -X POST https://api.timetriggers.io/tag-policies \-H "ttr-api-key: $TTR_API_KEY" \-H "Content-Type: application/json" \-d '{"tag": "unreliable-endpoint","maxConcurrent": 1,"requestTimeoutSeconds": 30,"retryMaxAttempts": 10,"retryStrategy": "exponential","retryInitialDelaySeconds": 5,"retryMaxDelaySeconds": 3600,"retryOn": "5xx+net"}'curl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: $TTR_API_KEY" \-H "ttr-url: https://unreliable-service.com/api" \-H "ttr-scheduled-at: now" \-H "ttr-tags: unreliable-endpoint" \-H "ttr-custom-key: unreliable-call-1" \-H "Content-Type: application/json" \-d '{"data": "value"}'
3. Rate-Limited Triggers
Limit the rate of trigger execution to avoid overwhelming your endpoint:
curl -X POST https://api.timetriggers.io/tag-policies \-H "ttr-api-key: $TTR_API_KEY" \-H "Content-Type: application/json" \-d '{"tag": "rate-limited","throughput": {"rate": 10,"per": 60}}'# This trigger will fire at most 10 times per minutecurl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: $TTR_API_KEY" \-H "ttr-url: https://your-service.com/api" \-H "ttr-scheduled-at: now" \-H "ttr-tags: rate-limited" \-H "ttr-custom-key: rate-limited-call" \-H "Content-Type: application/json" \-d '{"data": "value"}'
4. Bulk Trigger Management
Use the /declare endpoint to manage multiple triggers declaratively:
curl -X POST https://api.timetriggers.io/declare \-H "ttr-api-key: $TTR_API_KEY" \-H "Content-Type: application/json" \-d '{"tag": "my-batch","items": [{"customKey": "trigger-1","url": "https://your-service.com/endpoint-1","method": "POST","scheduledAt": "2026-10-18T10:00:00Z","headers": {"Content-Type": "application/json"},"body": "{\"id\": 1}","title": "First trigger"},{"customKey": "trigger-2","url": "https://your-service.com/endpoint-2","method": "POST","scheduledAt": "2026-10-18T11:00:00Z","headers": {"Content-Type": "application/json"},"body": "{\"id\": 2}","title": "Second trigger"}]}'
The /declare endpoint will:
- Create triggers that don't exist
- Update triggers that do exist with the same custom key
- Cancel triggers with the tag that aren't in the list
See Declare a set of triggers for more details.
5. Bulk Apply for Atomic Operations
Use /bulk for atomic create/update/cancel operations:
curl -X POST https://api.timetriggers.io/bulk \-H "ttr-api-key: $TTR_API_KEY" \-H "Content-Type: application/json" \-d '{"upserts": [{"customKey": "important-trigger","url": "https://your-service.com/important","method": "POST","scheduledAt": "2026-10-18T12:00:00Z","headers": {"Content-Type": "application/json"},"body": "{\"important\": true}","tags": ["critical"]}],"cancels": [{"customKey": "old-trigger"}]}'
See Bulk apply for the complete API.
Troubleshooting Production Issues
Trigger Not Firing
Check the dashboard at https://timetriggers.io/dashboard/triggers
- Is the trigger in "Scheduled" status?
- Has it passed its due time?
- Is it marked as "Skipped"?
Verify the scheduled time:
- Times are in UTC unless you specified a timezone
nowfires immediately (within seconds)- Past-dated triggers are skipped unless you use
ttr-run-missed: true
Check for authentication issues:
# Test your API keycurl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: $TTR_API_KEY" \-H "ttr-url: https://example.com/test" \-H "ttr-scheduled-at: now"# Should return 200 with a triggerId, or 401 if key is invalidCheck tag policies:
- A tag policy with
maxConcurrent: 0blocks all triggers with that tag - Throughput limits may delay trigger execution
- A tag policy with
Check your target:
- Is your endpoint reachable?
- Does it return a success status code?
- Are there any authentication issues with your target?
Trigger Fired But Target Didn't Receive It
Check the execution details in the dashboard:
- Look at the trigger page for execution history
- Check the response status code and error messages
Common issues:
- Target URL is incorrect
- Target requires headers that weren't sent
- Target has rate limiting or IP restrictions
- Network connectivity issues
High Trigger Failure Rate
Review tag policies:
- Increase retry attempts
- Adjust retry delays
- Check retry conditions (retry on 4xx vs 5xx)
Check your target:
- Is it returning appropriate error codes?
- Are timeouts configured correctly?
Monitor with alerts:
- Set up failure alerts in the dashboard
- Use Slack or email notifications
Production Checklist
Before deploying triggers to production:
- [ ] API key is valid and has sufficient quota
- [ ] Target endpoint is production-ready
- [ ] All required headers are included
- [ ] Scheduled times are correct (UTC vs local timezone)
- [ ] Custom keys are set for triggers that need to be updated
- [ ] Tags are set for organization and policy application
- [ ] Tag policies are configured appropriately (timeouts, retries, concurrency)
- [ ] Monitoring/alerting is in place
- [ ] API keys are stored securely (not in code)
- [ ] Quota usage is monitored
- [ ] Error handling is implemented in your target
API Reference
All endpoints and their full documentation:
| Endpoint | Purpose | Documentation |
|---|---|---|
POST /schedule | Create or update a trigger | Schedule a trigger |
DELETE /cancel | Cancel a trigger | Cancel a trigger |
POST /declare | Declarative trigger management | Declare a set of triggers |
POST /bulk | Bulk operations | Bulk apply |
GET /jobs | List triggers (dashboard) | Dashboard API |
GET /executions | List executions (dashboard) | Dashboard API |
Quota Management
Production accounts have monthly quota limits. Check your remaining quota:
curl -X POST https://api.timetriggers.io/schedule \-H "ttr-api-key: $TTR_API_KEY" \-H "ttr-url: https://example.com/test" \-H "ttr-scheduled-at: now"# Response includes "monthQuotaRemaining"
Or check in the dashboard under API Keys page.
See Quota for details on how quota works.
Security Best Practices
Never expose API keys in client-side code
- API calls should originate from your backend servers
- Use environment variables or secret managers
Use different keys for different environments
- Separate keys for production, staging, development
- This allows you to revoke one environment without affecting others
Rotate keys regularly
- Create new keys before decommissioning old ones
- Update all services to use the new key
- Delete the old key once all services are updated
Don't put secrets in URLs
- Credentials in URLs are visible in the dashboard
- Use headers for authentication instead
Use HTTPS
- All target URLs should use HTTPS
- API endpoints only accept HTTPS
Monitor key usage
- Review triggers created with each key periodically
- Delete keys that created suspicious triggers
Performance Considerations
Trigger creation rate: You can create triggers at any rate, but each
/schedulecall counts against your quota.Execution throughput: Tag policies control how quickly triggers execute. Without a throughput policy, triggers execute as quickly as possible.
Concurrency: Use tag policy concurrency limits to prevent overwhelming your endpoints.
Large payloads: Keep trigger bodies under 1 MB for reliable delivery.
Header size: Keep total request headers under 16 KB.
Additional Resources
- API Overview — Complete API documentation
- Dashboard Guide — Using the web dashboard
- Tag Policies — Configure execution behavior
- Quota Management — Understanding and managing your limits
- Errors Reference — Complete error codes and messages