# Event-Driven Architecture, Simplified

> Process events with type-safe pub/sub, automatic retry logic, and guaranteed ordering. Handle webhooks, streams, and custom events at global edge locations.

Canonical: https://events.do/

## In code

```typescript
import { $, db, ai, on, send, every } from 'sdk.do'

// ⚠️ Phase 2 Feature: Event system (`on`, `send`, `every`) is currently in development
// These primitives will show warnings in the current SDK implementation
// Full production support coming soon

// Complete event-driven e-commerce system with semantic patterns

// Event 1: Order Creation - Trigger entire fulfillment workflow
on($.Order.created, async (order) => {
  console.log('Order created:', order.id)

  // Decrement inventory for each item
  for (const item of order.items) {
    const product = await db.get('products', item.productId)
    await db.update('products', item.productId, {
      stock: product.stock - item.quantity
    })
  }

  // Send immediate confirmation email
  const confirmationEmail = await ai.generate({
    prompt: `Order confirmation for customer ${order.customerName}, order ${order.id}`,
    schema: $.Email.generates.Confirmation,
    model: 'claude-sonnet-4-5'
  })

  await send($.Email.sends.Confirmation, {
    to: order.customerEmail,
    subject: `Order Confirmation #${order.id}`,
    content: confirmationEmail.text
  })

  // Emit order confirmed event (cascading events)
  await send($.Order.confirmed, {
    orderId: order.id,
    customerId: order.customerId,
    total: order.total,
    confirmedAt: new Date().toISOString()
  })
})

// Event 2: Payment Processing - Update order status (with error handling)
on($.Payment.succeeded, async (payment) => {
  console.log('Payment succeeded:', payment.id)

  try {
    // Update order status
    await db.update('orders', payment.orderId, {
      status: 'paid',
      paymentId: payment.id,
      paidAt: new Date().toISOString()
    })

    // Trigger shipment preparation
    await send($.Shipment.prepares, {
      orderId: payment.orderId,
      priority: payment.amount > 1000 ? 'express' : 'standard'
    })

    // Analytics tracking
    await send($.Revenue.tracks, {
      amount: payment.amount,
      orderId: payment.orderId,
      customerId: payment.customerId
    })
  } catch (error) {
    // Handle payment processing failure
    console.error('Payment processing failed:', error)
    await send($.Payment.failed, {
      paymentId: payment.id,
      orderId: payment.orderId,
      error: error.message,
      timestamp: new Date().toISOString()
    })
  }
})

// Event 3: Shipment Status - Real-time customer updates
on($.Shipment.statusChanged, async (shipment) => {
  console.log('Shipment status changed:', shipment.status)

  // Get order and customer details
  const order = await db.get('orders', shipment.orderId)
  const customer = await db.get('customers', order.customerId)

  // AI-generated status update
  const statusUpdate = await ai.generate({
    prompt: `Shipping update: ${shipment.status} for order ${order.id}`,
    model: 'claude-sonnet-4-5'
  })

  // Send SMS notification for critical updates
  if (['shipped', 'out_for_delivery', 'delivered'].includes(shipment.status)) {
    await send($.SMS.sends.Notification, {
      to: customer.phone,
      message: statusUpdate.text
    })
  }

  // Update customer on order status
  await send($.Shipping.sends.Update, {
    to: customer.email,
    subject: `Your order is ${shipment.status}`,
    content: statusUpdate.text,
    trackingNumber: shipment.trackingNumber
  })
})

// Event 4: Webhook from Stripe - Automatic retry logic
on($.Webhook.Stripe.payment_intent_succeeded, async (event) => {
  console.log('Stripe webhook received:', event.id)

  // Parse Stripe event
  const paymentIntent = event.data.object

  // Emit internal payment succeeded event
  await send($.Payment.succeeded, {
    id: paymentIntent.id,
    orderId: paymentIntent.metadata.orderId,
    customerId: paymentIntent.metadata.customerId,
    amount: paymentIntent.amount / 100, // Convert from cents
    currency: paymentIntent.currency
  })
})

// Event 5: Customer Support - AI-powered ticket routing
on($.Support.Ticket.created, async (ticket) => {
  console.log('Support ticket created:', ticket.id)

  // AI classifies ticket urgency and category
  const classification = await ai.generate({
    prompt: `Classify this support ticket: ${ticket.message}`,
    schema: $.Support.analyzes.TicketClassification,
    model: 'claude-sonnet-4-5'
  })

  // Route to appropriate agent based on AI analysis
  const agent = classification.urgency === 'high' ? 'tier2' : 'tier1'

  await send($.Ticket.assigns, {
    ticketId: ticket.id,
    agent,
    category: classification.category,
    priority: classification.urgency
  })

  // Auto-reply with AI-generated response
  if (classification.canAutoResolve) {
    const response = await ai.generate({
      prompt: `Generate helpful response for: ${ticket.message}`,
      model: 'claude-sonnet-4-5'
    })

    await send($.Support.sends.AutoReply, {
      ticketId: ticket.id,
      customerId: ticket.customerId,
      content: response.text
    })
  }
})

// Scheduled Event: Daily Analytics Aggregation
every('0 0 * * *', async () => {
  console.log('Running daily analytics aggregation')

  // Aggregate all events from the past 24 hours
  const events = await db.list('events', {
    where: {
      timestamp: { $gte: new Date(Date.now() - 86400000) }
    },
    limit: 10000
  })

  // AI-powered insights
  const insights = await ai.generate({
    prompt: `Analyze daily business events and generate insights: ${JSON.stringify(events)}`,
    schema: $.Analytics.generates.DailyInsights,
    model: 'claude-sonnet-4-5'
  })

  // Store and broadcast insights
  await send($.Report.generates.Daily, {
    date: new Date().toISOString().split('T')[0],
    insights,
    eventCount: events.length
  })
})
```

## Frequently asked questions

### How does events.do differ from traditional message queues?

Runs at the edge with <50ms latency globally (vs 200-500ms per hop), no infrastructure to manage, automatic scaling to millions of events/second, and type-safe schemas with IDE autocomplete.

### What happens if event processing fails?

Automatic exponential backoff retry, dead letter queues for failed events, poison message detection, and full error tracking with distributed tracing and structured logging.

### Can I guarantee event ordering?

Yes, events within a partition key are strictly ordered with configurable exactly-once or at-least-once delivery semantics—global ordering available with throughput trade-offs.

### How do I handle high-volume event streams?

Automatic sharding, load balancing, and horizontal scaling process millions of events/second with batching, compression, window functions, and pay-per-event pricing.

### Can I replay or reprocess events?

Yes, all events stored with configurable retention (1-365 days) support replay from any timestamp or sequence number with time-travel queries and immutable audit logs.

## Part of Platform.do

events.do is one of the primitives of Platform.do. Every .do shares one grammar, Business-as-Code, and one SDK.

- What is Business-as-Code? https://platform.do/business-as-code
- Platform.do: https://platform.do/
- Docs: https://docs.platform.do
