Export SMS conversation history from Edge SQL to Cloud Storage as chunked JSON files, with a 4-stage Agent SDK pipeline that handles 10k+ messages — and texts you when the export is done. All on Telnyx Edge Compute, in under 350 lines of TypeScript.
What You'll Build
An SMS conversation exporter that:
- Ingests SMS messages via Telnyx Messaging webhooks into a per-actor SQL database
- Counts and chunks messages for export (configurable chunk size, default 500)
- Uploads each chunk as a separate JSON file to Cloud Storage
- Writes a manifest file listing all chunks with metadata
- Sends an SMS notification when the export is complete (zero-credential binding)
- Handles 10,000+ messages via non-blocking, self-requeuing pipeline stages
The entire system runs on Telnyx Edge Compute — no external database, no separate upload service, no cross-cloud latency.
Architecture
POST /export
│
▼
┌──────────────────────┐
│ ExportAgent │ (one actor per export job)
│ │
│ 1. countMessages() │──► SQL DB: SELECT COUNT(*)
│ 2. exportChunk() │──► SQL DB: SELECT chunk
│ │──► Cloud Storage: PUT JSON chunk
│ (re-queues │ (repeats until all chunks done)
│ until done) │
│ 3. writeManifest() │──► Cloud Storage: PUT manifest.json
│ 4. notifyComplete() │──► SMS via [telnyx] binding
└──────────────────────┘
Quick Start
1. Clone and install
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/sms-conversation-exporter
npm install
2. Configure
Edit telnyx.toml:
[storage.cloudstorage.EXPORT_STORAGE]
bucket_name = "<your-storage-bucket-name>"
region = "us-central-1"
[env_vars]
ALERT_PHONE = "+18005559876"
SENDER_PHONE = "+18005551234"
CHUNK_SIZE = "500"
3. Deploy
telnyx-edge secret set TELNYX_API_KEY KEY0123456789ABCDEF
telnyx-edge ship
4. Test the export
# Simulate 10,000 messages
curl -X POST https://your-deployment.telnyxcompute.com/simulate-bulk \
-H "Content-Type: application/json" \
-d '{"count": 10000}'
# Start the export
curl -X POST https://your-deployment.telnyxcompute.com/export
# Check progress
curl https://your-deployment.telnyxcompute.com/export/{exportId}
How the Pipeline Works
Agent SDK queue() — Non-Blocking Stages
Each export job gets its own ExportAgent actor instance. The pipeline uses this.queue() to chain stages without blocking the HTTP request:
async start(params: { exportId: string; conversationFilter: string | null }): Promise<void> {
await this.setState({ exportId: params.exportId, status: "counting" });
await this.queue("countMessages");
}
Self-Requeuing Chunks
The key pattern is the self-requeuing exportChunk() stage:
async exportChunk(): Promise<void> {
const state = await this.getState();
const offset = state.chunkIndex * chunkSize;
const rows = this.ctx.storage.sql.exec(
"SELECT * FROM messages ORDER BY timestamp ASC LIMIT ? OFFSET ?",
chunkSize, offset
).toArray();
await this.env.EXPORT_STORAGE.put(
`exports/${state.exportId}/chunk-${state.chunkIndex}.json`,
JSON.stringify({ messages: rows })
);
if (state.chunkIndex + 1 < state.totalChunks) {
await this.queue("exportChunk"); // schedule next chunk
} else {
await this.queue("writeManifest");
}
}
Each chunk runs as a separate, non-blocking stage. The actor isn't blocked, progress is visible at any time via GET /export/:id, and a chunk failure is captured in state.
Zero-Credential SMS Notification
async notifyComplete(): Promise<void> {
await this.env.TELNYX.messages.send({
from: this.env.SENDER_PHONE,
to: this.env.ALERT_PHONE,
text: `Export complete: ${state.exportedMessages} messages in ${state.uploadedChunks.length} chunk(s).`
});
}
No API key in code. The [telnyx] binding in telnyx.toml gives the actor access to the Messaging API — the platform handles authentication.
Chunked Output in Cloud Storage
exports/export-1234567890-abc123/
├── chunk-0000.json (messages 0–499)
├── chunk-0001.json (messages 500–999)
├── chunk-0002.json (messages 1000–1499)
├── ...
└── manifest.json (metadata: total count, chunk list)
Each chunk is self-contained with metadata — exportId, chunkIndex, totalChunks, totalMessages. Process chunks independently in Spark, BigQuery, or any data pipeline.
API Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /webhooks/messaging |
Messaging webhook (ingests SMS into SQL) |
| POST | /export |
Start a chunked export job |
| GET | /export/:id |
Get export status and progress |
| GET | /messages |
List messages in SQL DB |
| GET | /messages/count |
Get total message count |
| POST | /seed |
Add a single test message |
| POST | /simulate-bulk |
Bulk insert test messages (default 10k) |
Use Cases
- Compliance archival — Export SMS conversation history for regulatory compliance
- Data migration — Move SMS data from Edge SQL to a data warehouse via Cloud Storage
- Backup — Periodic JSON exports of all conversations to Cloud Storage
- Analytics — Export conversation data for offline analysis
Top comments (0)