This guide walks you through setting up Twilio Sync for conversation state management and rate limiting.
Twilio Sync is a serverless state management service that enables your Twilio Functions to store and retrieve data without managing infrastructure. This project uses Sync for:
- Conversation History Storage - Stores OpenAI message history between function calls
- Rate Limiting - Tracks daily API call counts to prevent cost overruns
Before (URL-based storage):
- ❌ 2KB URL limit - conversations trimmed after ~10 exchanges
- ❌ Conversation history visible in logs (security risk)
- ❌ No encryption
- ❌ No rate limiting
After (Sync-based storage):
- ✅ Unlimited conversation length
- ✅ Encrypted storage with automatic 1-hour expiration
- ✅ Rate limiting: 1000 OpenAI calls/day (configurable)
- ✅ Cleaner URLs with only essential parameters
- Twilio Account (free trial works)
- Twilio CLI installed (guide)
- Go to Twilio Console → Sync → Services
- Click "Create new Sync Service"
- Name it:
synthetic-call-data-sync(or your preference) - Click "Create"
- Copy the Service SID (starts with
IS...)
# Create Sync service
twilio api:sync:v1:services:create \
--friendly-name "synthetic-call-data-sync"
# Output will include the SID
# Service SID: ISxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAdd the Sync Service SID to your .env file:
SYNC_SERVICE_SID=ISxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBy default, the system allows 1000 OpenAI calls per day (~$3/day at gpt-4o-mini pricing).
Edit .env:
# Conservative (low cost)
MAX_DAILY_CALLS=100 # ~$0.30/day
# Default (moderate usage)
MAX_DAILY_CALLS=1000 # ~$3/day
# High volume (enterprise)
MAX_DAILY_CALLS=10000 # ~$30/dayWhen limit is reached:
- OpenAI API calls are blocked
- Caller hears: "I apologize, but the service has reached its daily usage limit. Please try again tomorrow."
- Call is hung up gracefully
- Error logged with current count
Reset Schedule:
- Limits reset at midnight UTC automatically
- No manual intervention required
- Sync documents auto-expire after 24 hours
Check current usage:
# View today's call count in Twilio Console
# Navigate to: Sync → Services → Your Service → Documents
# Look for document named: rate_limit_YYYY-MM-DDOr programmatically:
const { getRateLimitStatus } = require('./functions/utils/sync-manager');
const status = await getRateLimitStatus(context);
console.log(`Calls today: ${status.currentCount}/${status.limit}`);
console.log(`Remaining: ${status.remaining}`);
console.log(`Resets at: ${status.resetsAt}`);Run the pre-deployment check:
npm run pre-deployExpected output:
✓ Environment variables validated
✓ SYNC_SERVICE_SID found
✓ Rate limit configured (1000 calls/day)
Each conversation is stored in a Sync Document with:
- Unique Name:
conversation_{conferenceId} - Data: Array of OpenAI messages (without system prompt)
- TTL: 1 hour (auto-deleted after conference ends)
// Example Sync document
{
"uniqueName": "conversation_CF123456",
"data": {
"messages": [
{ "role": "user", "content": "Hello" },
{ "role": "assistant", "content": "Hi! How can I help?" },
{ "role": "user", "content": "I have a question..." }
],
"lastUpdated": "2025-10-09T12:34:56.789Z"
},
"ttl": 3600
}Daily call counts are stored in date-stamped documents:
- Unique Name:
rate_limit_2025-10-09 - Data:
{ count: 42, lastUpdated: "..." } - TTL: 24 hours (auto-resets daily)
// Example rate limit document
{
"uniqueName": "rate_limit_2025-10-09",
"data": {
"count": 42,
"lastUpdated": "2025-10-09T12:34:56.789Z"
},
"ttl": 86400
}Solution: Add SYNC_SERVICE_SID to your .env file and redeploy:
echo "SYNC_SERVICE_SID=ISxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" >> .env
npm run deployCause: Sync service unavailable or credentials invalid
Solution:
- Verify
SYNC_SERVICE_SIDis correct - Check Twilio account has Sync enabled
- Verify auth token is valid
Note: System operates in "fail-open" mode - if rate limiting fails, requests are allowed (with warning logs)
Check:
- Sync service is active:
twilio api:sync:v1:services:fetch --sid ISxxxxxx - Documents are being created: View in Twilio Console → Sync → Documents
- TTL hasn't expired (conversations expire after 1 hour)
Expected behavior: Limits reset automatically at midnight UTC
If stuck:
- Delete the rate limit document manually
- Or wait until TTL expires (24 hours)
# Delete today's rate limit document
twilio api:sync:v1:services:documents:remove \
--service-sid ISxxxxxx \
--sid rate_limit_2025-10-09- Free Tier: 50,000 Sync operations/month
- Paid: $0.05 per 1,000 operations after free tier
For 1,000 conversations/day:
- Operations per conversation: ~10-15 (read + write + rate check)
- Monthly operations: 1,000 × 30 × 12 = 360,000 ops
- Cost: (360,000 - 50,000) / 1,000 × $0.05 = $15.50/month
vs. OpenAI Costs:
- 1,000 calls/day × 30 days × $0.003/call = $90/month
Sync is ~1.7% of total AI costs.
When deploying this as a template for others:
-
Document clearly in README:
- Sync Service SID is required
- Rate limits MUST be configured per user's budget
- Default 1000 calls/day may be too high/low for their use case
-
Provide configuration guidance:
- Link to cost calculator
- Explain pricing implications
- Show examples for different usage levels
-
Consider adding to setup script:
# Auto-create Sync service during setup npm run setup # Creates Sync service and adds to .env
- Never commit
.envfile - Contains sensitive SYNC_SERVICE_SID - Use environment variables - Never hardcode SIDs in code
- Set appropriate TTLs - Don't store conversation data longer than needed
- Monitor usage - Set up alerts for unusual Sync activity
- Rotate credentials - Regenerate auth tokens periodically
- ✅ Sync configured? → Continue to Deployment Guide
- ❓ Need help? → Check Troubleshooting
- 📊 Want to monitor? → Set up CloudWatch integration