Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt

Use this file to discover all available pages before exploring further.

Best practices for Edge Compute based on production patterns and common issues.

Configuration

Use Environment Variables for Secrets

Never hardcode secrets. Use the secrets API:
telnyx-edge secrets add --name API_KEY --value "sk-..."
Access in code:
const apiKey = process.env.API_KEY;

Set Appropriate Timeouts

Configure timeouts based on your function’s needs:
# func.toml
[edge_compute]
timeout_seconds = 30  # Default: 30, Max: 300

Use Descriptive Function Names

Function names become part of your URL. Choose wisely:
# ✅ Good
telnyx-edge new-func --name=user-api
telnyx-edge new-func --name=webhook-handler

# ❌ Bad
telnyx-edge new-func --name=func1
telnyx-edge new-func --name=test

Performance

Reuse Connections

Initialize clients once at module level, not per request:
// ✅ Good — client initialized once, reused across requests
const client = new HttpClient({ timeout: 5000 });

export async function handler(request) {
    const response = await client.get('https://api.example.com/data');
    return new Response(JSON.stringify(response));
}
// ❌ Bad — new client created every request
export async function handler(request) {
    const client = new HttpClient({ timeout: 5000 });
    const response = await client.get('https://api.example.com/data');
    return new Response(JSON.stringify(response));
}

Minimize Cold Starts

Cold starts happen when a new container spins up. Reduce their impact:
  1. Lazy-load dependencies — Only import what you need, when you need it
  2. Keep functions small — Smaller code = faster load
  3. Use lightweight frameworks — Hono over Express, FastAPI over Django
// ✅ Good — lazy load heavy dependency
let heavyLib;
function getHeavyLib() {
    if (!heavyLib) {
        heavyLib = require('heavy-library');
    }
    return heavyLib;
}

export async function handler(request) {
    if (needsHeavyProcessing(request)) {
        const lib = getHeavyLib();
        // use lib
    }
}

Cache Expensive Operations

Use KV for caching API responses and computed data:
async function getUser(userId) {
    // Check cache first
    const cached = await kv.get(`user:${userId}`);
    if (cached) return JSON.parse(cached);
    
    // Fetch from origin
    const user = await fetchUserFromDB(userId);
    
    // Cache for 5 minutes
    await kv.put(`user:${userId}`, JSON.stringify(user), { ttl: 300 });
    
    return user;
}

Reliability

Handle Errors Gracefully

Always return proper error responses:
export async function handler(request) {
    try {
        const data = await riskyOperation();
        return new Response(JSON.stringify(data), {
            headers: { "Content-Type": "application/json" }
        });
    } catch (error) {
        console.error("Operation failed:", error.message);
        
        return new Response(JSON.stringify({
            error: "Internal server error",
            requestId: request.headers.get("X-Request-ID")
        }), {
            status: 500,
            headers: { "Content-Type": "application/json" }
        });
    }
}

Set Timeouts on External Calls

Don’t let slow external services hang your function:
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);

try {
    const response = await fetch('https://api.example.com/data', {
        signal: controller.signal
    });
    clearTimeout(timeout);
    return response;
} catch (error) {
    if (error.name === 'AbortError') {
        return new Response('External service timeout', { status: 504 });
    }
    throw error;
}

Implement Retries with Backoff

For critical operations, add retry logic:
async function fetchWithRetry(url, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            const response = await fetch(url);
            if (response.ok) return response;
            
            // Don't retry client errors
            if (response.status < 500) throw new Error(`HTTP ${response.status}`);
        } catch (error) {
            if (i === maxRetries - 1) throw error;
            
            // Exponential backoff
            await new Promise(r => setTimeout(r, Math.pow(2, i) * 100));
        }
    }
}

Security

Validate Input

Never trust user input:
export async function handler(request) {
    const body = await request.json();
    
    // Validate required fields
    if (!body.email || typeof body.email !== 'string') {
        return new Response(JSON.stringify({ error: 'Invalid email' }), {
            status: 400
        });
    }
    
    // Validate format
    if (!isValidEmail(body.email)) {
        return new Response(JSON.stringify({ error: 'Invalid email format' }), {
            status: 400
        });
    }
    
    // Sanitize
    const email = body.email.toLowerCase().trim();
    // ...
}

Use HTTPS for External Calls

Always use HTTPS when calling external services:
// ✅ Good
await fetch('https://api.example.com/data');

// ❌ Bad — insecure
await fetch('http://api.example.com/data');

Don’t Log Sensitive Data

Be careful what you log:
// ✅ Good — log request metadata
console.log(`Request: ${request.method} ${request.url}`);

// ❌ Bad — logging secrets
console.log(`API Key: ${process.env.API_KEY}`);

// ❌ Bad — logging full request body (may contain PII)
console.log(`Body: ${JSON.stringify(body)}`);

Observability

Add Request IDs

Track requests through your system:
export async function handler(request) {
    const requestId = request.headers.get('X-Request-ID') || crypto.randomUUID();
    
    console.log(`[${requestId}] Processing request`);
    
    // Include in response
    return new Response(JSON.stringify({ data }), {
        headers: {
            "Content-Type": "application/json",
            "X-Request-ID": requestId
        }
    });
}

Log at Appropriate Levels

Use log levels effectively:
const logger = {
    debug: (msg) => process.env.LOG_LEVEL === 'debug' && console.log(`[DEBUG] ${msg}`),
    info: (msg) => console.log(`[INFO] ${msg}`),
    warn: (msg) => console.warn(`[WARN] ${msg}`),
    error: (msg) => console.error(`[ERROR] ${msg}`)
};

// Use appropriately
logger.debug(`Cache hit for key: ${key}`);      // Verbose debugging
logger.info(`User ${userId} created`);           // Normal operations
logger.warn(`Retry attempt ${i} for ${url}`);    // Concerning but handled
logger.error(`Database connection failed`);      // Errors requiring attention