Delivery Strategies
VaultSandbox Client supports two email delivery strategies: Server-Sent Events (SSE) for real-time updates and Polling for compatibility. The SDK intelligently chooses the best strategy automatically or allows manual configuration.
Overview
Section titled “Overview”When you wait for emails or subscribe to new email notifications, the SDK needs to know when emails arrive. It does this using one of two strategies:
- SSE (Server-Sent Events): Real-time push notifications from the server
- Polling: Periodic checking for new emails
Strategy Comparison
Section titled “Strategy Comparison”| Feature | SSE | Polling |
|---|---|---|
| Latency | Near-instant (~100ms) | Poll interval (default: 2s) |
| Server Load | Lower (persistent connection) | Higher (repeated requests) |
| Network Traffic | Lower (only when emails arrive) | Higher (constant polling) |
| Compatibility | Requires persistent connections | Works everywhere |
| Firewall/Proxy | May be blocked | Always works |
| Battery Impact | Lower (push-based) | Higher (constant requests) |
Auto Strategy (Recommended)
Section titled “Auto Strategy (Recommended)”The default auto strategy automatically selects the best delivery method:
- Tries SSE first - Attempts to establish an SSE connection
- Falls back to polling - If SSE fails or is unavailable, uses polling
- Adapts to environment - Works seamlessly in different network conditions
import { VaultSandboxClient } from '@vaultsandbox/client';
// Auto strategy (default)const client = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'auto', // Default, can be omitted});
// SDK will automatically choose the best strategyconst inbox = await client.createInbox();const email = await inbox.waitForEmail({ timeout: 10000 });When Auto Chooses SSE
Section titled “When Auto Chooses SSE”- Gateway supports SSE
- Network allows persistent connections
- No restrictive proxy/firewall
When Auto Falls Back to Polling
Section titled “When Auto Falls Back to Polling”- Gateway doesn’t support SSE
- SSE connection fails
- Behind restrictive proxy/firewall
- Network requires periodic reconnection
SSE Strategy
Section titled “SSE Strategy”Server-Sent Events provide real-time push notifications when emails arrive.
Advantages
Section titled “Advantages”- Near-instant delivery: Emails appear within milliseconds
- Lower server load: Single persistent connection
- Efficient: Only transmits when emails arrive
- Battery-friendly: No constant polling
Configuration
Section titled “Configuration”const client = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'sse', sseReconnectInterval: 5000, // Wait 5s before reconnecting sseMaxReconnectAttempts: 10, // Try up to 10 reconnections});SSE Configuration Options
Section titled “SSE Configuration Options”| Option | Type | Default | Description |
|---|---|---|---|
sseReconnectInterval | number | 5000 | Initial delay before reconnection (ms) |
sseMaxReconnectAttempts | number | 10 | Maximum reconnection attempts |
Reconnection Behavior
Section titled “Reconnection Behavior”SSE uses exponential backoff for reconnections:
1st attempt: sseReconnectInterval (5s)2nd attempt: sseReconnectInterval * 2 (10s)3rd attempt: sseReconnectInterval * 4 (20s)...up to sseMaxReconnectAttemptsExample Usage
Section titled “Example Usage”const client = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'sse',});
const inbox = await client.createInbox();
// Real-time subscription (uses SSE)const subscription = inbox.onNewEmail((email) => { console.log(`Instant notification: ${email.subject}`);});
// Waiting also uses SSE (faster than polling)const email = await inbox.waitForEmail({ timeout: 10000, subject: /Welcome/,});
subscription.unsubscribe();When to Use SSE
Section titled “When to Use SSE”- Real-time monitoring: When you need instant email notifications
- Long-running tests: Reduces overall test time
- High email volume: More efficient than polling
- Development/local: Fast feedback during development
Limitations
Section titled “Limitations”- Requires persistent HTTP connection support
- May not work behind some corporate proxies
- Some cloud environments may close long-lived connections
- Requires server-side SSE support
Polling Strategy
Section titled “Polling Strategy”Polling periodically checks for new emails at a configured interval.
Advantages
Section titled “Advantages”- Universal compatibility: Works in all environments
- Firewall-friendly: Standard HTTP requests
- Predictable: Easy to reason about behavior
- Resilient: Automatically recovers from transient failures
Configuration
Section titled “Configuration”const client = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'polling', pollingInterval: 2000, // Check every 2 seconds});Polling Configuration Options
Section titled “Polling Configuration Options”| Option | Type | Default | Description |
|---|---|---|---|
pollingInterval | number | 2000 | How often to poll for emails (ms) |
Example Usage
Section titled “Example Usage”const client = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'polling', pollingInterval: 1000, // Poll every 1 second});
const inbox = await client.createInbox();
// Polling-based subscriptionconst subscription = inbox.onNewEmail((email) => { console.log(`Polled notification: ${email.subject}`);});
// Waiting uses polling (checks every pollingInterval)const email = await inbox.waitForEmail({ timeout: 10000, subject: /Welcome/,});
subscription.unsubscribe();Choosing Poll Interval
Section titled “Choosing Poll Interval”Different intervals suit different scenarios:
// Fast polling (500ms) - Development/local testingconst fastClient = new VaultSandboxClient({ url: 'http://localhost:3000', apiKey: 'dev-key', strategy: 'polling', pollingInterval: 500,});
// Standard polling (2000ms) - Default, good balanceconst standardClient = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'polling', pollingInterval: 2000,});
// Slow polling (5000ms) - CI/CD or rate-limited environmentsconst slowClient = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'polling', pollingInterval: 5000,});When to Use Polling
Section titled “When to Use Polling”- Corporate networks: Restrictive firewall/proxy environments
- CI/CD pipelines: Guaranteed compatibility
- Rate-limited APIs: Avoid hitting request limits
- Debugging: Predictable request timing
- Low email volume: Polling overhead is minimal
Performance Optimization
Section titled “Performance Optimization”For waitForEmailCount(), you can override the polling interval:
// Default client polling: 2sconst client = new VaultSandboxClient({ url: 'https://smtp.vaultsandbox.com', apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'polling', pollingInterval: 2000,});
// Override for specific operation (faster)await inbox.waitForEmailCount(5, { timeout: 30000, pollInterval: 1000, // Check every 1s for this operation});Choosing the Right Strategy
Section titled “Choosing the Right Strategy”Use Auto (Default)
Section titled “Use Auto (Default)”For most use cases, let the SDK choose:
const client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, // strategy: 'auto' is implicit});Best for:
- General testing
- Unknown network conditions
- Mixed environments (dev, staging, CI)
- When you want it to “just work”
Force SSE
Section titled “Force SSE”When you need guaranteed real-time performance:
const client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'sse',});Best for:
- Local development (known to support SSE)
- Real-time monitoring dashboards
- High-volume email testing
- Latency-sensitive tests
Caveat: Will throw SSEError if SSE is unavailable.
Force Polling
Section titled “Force Polling”When compatibility is more important than speed:
const client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'polling', pollingInterval: process.env.CI ? 3000 : 1000,});Best for:
- CI/CD environments (guaranteed to work)
- Corporate networks with restrictive proxies
- When SSE is known to be problematic
- Rate-limited scenarios
Environment-Specific Configuration
Section titled “Environment-Specific Configuration”Development
Section titled “Development”Fast feedback with SSE:
VAULTSANDBOX_URL=http://localhost:3000VAULTSANDBOX_STRATEGY=sse
// config.jsconst client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: process.env.VAULTSANDBOX_STRATEGY || 'auto',});Reliable polling:
VAULTSANDBOX_URL=https://smtp.vaultsandbox.comVAULTSANDBOX_STRATEGY=pollingVAULTSANDBOX_POLLING_INTERVAL=3000
// config.jsconst client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: process.env.VAULTSANDBOX_STRATEGY || 'auto', pollingInterval: parseInt(process.env.VAULTSANDBOX_POLLING_INTERVAL || '2000'),});Production Testing
Section titled “Production Testing”Auto with tuned reconnection:
const client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'auto', // SSE config (if available) sseReconnectInterval: 10000, sseMaxReconnectAttempts: 5, // Polling fallback config pollingInterval: 5000,});Monitoring Strategy Performance
Section titled “Monitoring Strategy Performance”Check Active Strategy
Section titled “Check Active Strategy”const client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'auto',});
const inbox = await client.createInbox();
// Subscribe and check what strategy is being usedconst subscription = inbox.onNewEmail((email) => { console.log(`Email received: ${email.subject}`);});
// The SDK will log which strategy it's using// Check logs for: "Using SSE strategy" or "Using polling strategy"Measure Email Delivery Latency
Section titled “Measure Email Delivery Latency”async function measureDeliveryLatency() { const client = new VaultSandboxClient({ url, apiKey }); const inbox = await client.createInbox();
const startTime = Date.now();
// Send email await sendTestEmail(inbox.emailAddress);
// Wait for email const email = await inbox.waitForEmail({ timeout: 30000 });
const latency = Date.now() - startTime; console.log(`Email delivery latency: ${latency}ms`);
await inbox.delete();}Compare Strategies
Section titled “Compare Strategies”async function compareStrategies() { // Test SSE const sseClient = new VaultSandboxClient({ url, apiKey, strategy: 'sse', }); const sseInbox = await sseClient.createInbox(); const sseStart = Date.now(); await sendTestEmail(sseInbox.emailAddress); await sseInbox.waitForEmail({ timeout: 10000 }); const sseLatency = Date.now() - sseStart;
// Test Polling const pollClient = new VaultSandboxClient({ url, apiKey, strategy: 'polling', pollingInterval: 2000, }); const pollInbox = await pollClient.createInbox(); const pollStart = Date.now(); await sendTestEmail(pollInbox.emailAddress); await pollInbox.waitForEmail({ timeout: 10000 }); const pollLatency = Date.now() - pollStart;
console.log(`SSE latency: ${sseLatency}ms`); console.log(`Polling latency: ${pollLatency}ms`); console.log(`Difference: ${pollLatency - sseLatency}ms`);
await sseInbox.delete(); await pollInbox.delete();}Troubleshooting
Section titled “Troubleshooting”SSE Connection Failures
Section titled “SSE Connection Failures”import { SSEError } from '@vaultsandbox/client';
try { const client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'sse', });
const inbox = await client.createInbox(); // Use inbox...} catch (error) { if (error instanceof SSEError) { console.error('SSE failed:', error.message); console.log('Falling back to polling...');
// Recreate with polling const client = new VaultSandboxClient({ url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, strategy: 'polling', });
const inbox = await client.createInbox(); // Continue with polling... }}Polling Too Slow
Section titled “Polling Too Slow”If emails arrive slowly with polling:
// Problem: Default 2s polling is too slowconst client = new VaultSandboxClient({ url, apiKey, strategy: 'polling', pollingInterval: 2000, // Check every 2s});
// Solution 1: Faster pollingconst fasterClient = new VaultSandboxClient({ url, apiKey, strategy: 'polling', pollingInterval: 500, // Check every 500ms});
// Solution 2: Use SSE if availableconst sseClient = new VaultSandboxClient({ url, apiKey, strategy: 'sse', // Real-time delivery});
// Solution 3: Override for specific waitawait inbox.waitForEmail({ timeout: 10000, pollInterval: 500, // Fast polling for this operation});Best Practices
Section titled “Best Practices”1. Use Auto Strategy by Default
Section titled “1. Use Auto Strategy by Default”Let the SDK choose unless you have specific requirements:
// Good: Let SDK chooseconst client = new VaultSandboxClient({ url, apiKey });
// Only specify when neededconst ciClient = new VaultSandboxClient({ url, apiKey, strategy: 'polling', // CI needs guaranteed compatibility});2. Tune for Environment
Section titled “2. Tune for Environment”Configure differently for each environment:
function createClient() { const config = { url: process.env.VAULTSANDBOX_URL, apiKey: process.env.VAULTSANDBOX_API_KEY, };
if (process.env.CI) { // CI: Reliable polling config.strategy = 'polling'; config.pollingInterval = 3000; } else if (process.env.NODE_ENV === 'development') { // Dev: Fast SSE config.strategy = 'sse'; } else { // Production: Auto with tuning config.strategy = 'auto'; config.sseReconnectInterval = 5000; config.pollingInterval = 2000; }
return new VaultSandboxClient(config);}3. Handle SSE Gracefully
Section titled “3. Handle SSE Gracefully”Always have a fallback if forcing SSE:
async function createClientWithFallback() { try { return new VaultSandboxClient({ url, apiKey, strategy: 'sse' }); } catch (error) { if (error instanceof SSEError) { console.warn('SSE unavailable, using polling'); return new VaultSandboxClient({ url, apiKey, strategy: 'polling' }); } throw error; }}4. Don’t Poll Too Aggressively
Section titled “4. Don’t Poll Too Aggressively”Avoid very short polling intervals in production:
// Avoid: Too aggressiveconst client = new VaultSandboxClient({ url, apiKey, strategy: 'polling', pollingInterval: 100, // 100ms - too frequent!});
// Good: Reasonable intervalconst client = new VaultSandboxClient({ url, apiKey, strategy: 'polling', pollingInterval: 2000, // 2s - balanced});Next Steps
Section titled “Next Steps”- Real-time Monitoring Guide - Using subscriptions
- Configuration Reference - All config options
- Error Handling - Handle SSE errors
- CI/CD Integration - Strategy for CI environments