.do

Best Practices

Proven patterns and guidelines for building successful services

Proven patterns and guidelines for building successful, scalable, and profitable services.

Service Design

1. Single Responsibility Principle

Each service should do one thing well:

// Good: Focused service
const emailValidationService = await $.Service.create({
  name: 'Email Validator',
  purpose: 'Validate email addresses',
  does: ['syntax-check', 'domain-validation', 'smtp-verification'],
  doesNot: ['email-marketing', 'email-sending', 'contact-management'],
})

// Avoid: Kitchen sink service
const everythingService = await $.Service.create({
  name: 'Everything Service',
  does: [
    'email-validation',
    'crm-sync',
    'content-generation',
    'payment-processing',
    // ... too many responsibilities
  ],
})

Why:

  • Easier to test and maintain
  • Simpler pricing models
  • Better composability
  • Clearer value proposition

2. Clear Input/Output Contracts

Define explicit schemas:

const service = await $.Service.create({
  name: 'Document Summarizer',

  // Explicit input schema
  input: {
    schema: {
      document: {
        type: 'string',
        required: true,
        minLength: 100,
        maxLength: 100000,
        description: 'The document text to summarize',
      },
      maxLength: {
        type: 'number',
        required: false,
        default: 500,
        min: 100,
        max: 2000,
        description: 'Maximum length of summary in words',
      },
      style: {
        type: 'enum',
        required: false,
        values: ['concise', 'detailed', 'bullet-points'],
        default: 'concise',
        description: 'Summary style',
      },
    },
  },

  // Explicit output schema
  output: {
    schema: {
      summary: {
        type: 'string',
        description: 'The generated summary',
      },
      keyPoints: {
        type: 'array',
        items: 'string',
        description: 'Key points extracted from document',
      },
      wordCount: {
        type: 'number',
        description: 'Word count of summary',
      },
      confidence: {
        type: 'number',
        min: 0,
        max: 1,
        description: 'Confidence score of summarization',
      },
    },
  },
})

3. Graceful Degradation

Handle failures elegantly:

on.ServiceRequest.created(async (request) => {
  try {
    // Try primary method
    const result = await primaryMethod(request)
    return result
  } catch (primaryError) {
    try {
      // Fallback to secondary method
      logger.warn('Primary method failed, using fallback', { error: primaryError })
      const result = await fallbackMethod(request)
      return result
    } catch (fallbackError) {
      // Partial result if possible
      const partial = await attemptPartialResult(request)

      if (partial) {
        send.ServiceResult.deliver({
          requestId: request.id,
          outputs: partial,
          warnings: ['Partial result due to errors'],
          quality: 'degraded',
        })
        return
      }

      // Final failure with helpful message
      send.ServiceRequest.fail({
        requestId: request.id,
        error: 'Service temporarily unavailable',
        retryable: true,
        retryAfter: 300, // seconds
        supportContact: '[email protected]',
      })
    }
  }
})

Quality Assurance

1. Validate Everything

Never trust input data:

async function validateRequest(request: ServiceRequest, service: Service) {
  const errors = []

  // Type validation
  for (const [field, schema] of Object.entries(service.input.schema)) {
    const value = request.inputs[field]

    if (schema.required && value === undefined) {
      errors.push(`Missing required field: ${field}`)
      continue
    }

    if (value !== undefined) {
      // Type check
      if (typeof value !== schema.type) {
        errors.push(`Invalid type for ${field}: expected ${schema.type}, got ${typeof value}`)
      }

      // Range checks
      if (schema.min !== undefined && value < schema.min) {
        errors.push(`${field} must be >= ${schema.min}`)
      }

      if (schema.max !== undefined && value > schema.max) {
        errors.push(`${field} must be <= ${schema.max}`)
      }

      // Enum validation
      if (schema.values && !schema.values.includes(value)) {
        errors.push(`${field} must be one of: ${schema.values.join(', ')}`)
      }

      // Custom validation
      if (schema.validate) {
        const customError = schema.validate(value)
        if (customError) {
          errors.push(customError)
        }
      }
    }
  }

  // Business rule validation
  if (service.validation?.rules) {
    for (const rule of service.validation.rules) {
      if (!rule.check(request.inputs)) {
        errors.push(rule.message)
      }
    }
  }

  return {
    valid: errors.length === 0,
    errors,
  }
}

2. Implement Quality Checks

Verify output quality before delivery:

async function qualityCheck(result: any, service: Service) {
  const checks = []

  // Completeness check
  for (const requiredField of service.output.required) {
    if (!result[requiredField]) {
      checks.push({
        check: 'completeness',
        field: requiredField,
        passed: false,
        message: `Missing required output: ${requiredField}`,
      })
    }
  }

  // AI quality assessment
  if (service.quality?.aiCheck) {
    const assessment = await ai.evaluate({
      model: 'gpt-5',
      output: result,
      criteria: service.quality.criteria,
    })

    checks.push({
      check: 'ai-quality',
      passed: assessment.score >= service.quality.threshold,
      score: assessment.score,
      issues: assessment.issues,
    })
  }

  // Specific quality metrics
  if (service.type === $.ServiceType.ContentGeneration) {
    // Readability
    const readability = calculateReadability(result.content)
    checks.push({
      check: 'readability',
      passed: readability >= 60,
      score: readability,
    })

    // Uniqueness
    const uniqueness = await checkPlagiarism(result.content)
    checks.push({
      check: 'uniqueness',
      passed: uniqueness >= 0.95,
      score: uniqueness,
    })
  }

  const allPassed = checks.every((c) => c.passed)

  return {
    passed: allPassed,
    checks,
    overallScore: checks.reduce((sum, c) => sum + (c.score || 0), 0) / checks.length,
  }
}

3. Comprehensive Testing

Test everything before deployment:

// Unit tests
describe('Email Validator Service', () => {
  test('validates correct email', async () => {
    const result = await service.validate('[email protected]')
    expect(result.valid).toBe(true)
  })

  test('rejects invalid email', async () => {
    const result = await service.validate('invalid-email')
    expect(result.valid).toBe(false)
    expect(result.reason).toBeDefined()
  })

  test('handles edge cases', async () => {
    const edgeCases = ['[email protected]', '[email protected]', '[email protected]']

    for (const email of edgeCases) {
      const result = await service.validate(email)
      expect(result.valid).toBe(true)
    }
  })
})

// Integration tests
describe('Email Validator Integration', () => {
  test('integrates with SMTP verification', async () => {
    const result = await service.validate('[email protected]', {
      smtpCheck: true,
    })

    expect(result.smtpValid).toBeDefined()
  })
})

// Load tests
describe('Email Validator Performance', () => {
  test('handles concurrent requests', async () => {
    const emails = generateTestEmails(1000)

    const start = Date.now()
    const results = await Promise.all(emails.map((email) => service.validate(email)))
    const duration = Date.now() - start

    expect(results.length).toBe(1000)
    expect(duration).toBeLessThan(10000) // Under 10 seconds
  })
})

Performance Optimization

1. Caching Strategy

Cache expensive operations:

import { cache } from 'sdk.do'

// Cache configuration
const cacheConfig = {
  ttl: 3600, // 1 hour
  maxSize: 1000,
  strategy: 'lru', // Least Recently Used
}

// Cache expensive AI operations
async function generateWithCache(prompt: string, options: any) {
  const cacheKey = `ai:${hash(prompt)}:${hash(options)}`

  // Check cache
  const cached = await cache.get(cacheKey)
  if (cached) {
    logger.debug('cache.hit', { key: cacheKey })
    return cached
  }

  // Generate if not cached
  logger.debug('cache.miss', { key: cacheKey })
  const result = await ai.generate({
    model: 'gpt-5',
    prompt,
    ...options,
  })

  // Store in cache
  await cache.set(cacheKey, result, cacheConfig.ttl)

  return result
}

// Cache database queries
async function getUserWithCache(userId: string) {
  return await cache.getOrSet(
    `user:${userId}`,
    async () => await db.Users.findOne({ id: userId }),
    300 // 5 minutes
  )
}

// Smart cache invalidation
on.User.updated(async (user) => {
  cache.delete(`user:${user.id}`)
})

2. Batch Processing

Process multiple items efficiently:

// Batch similar requests
class RequestBatcher {
  private queue: Request[] = []
  private timer: NodeJS.Timeout | null = null
  private batchSize = 50
  private maxWaitTime = 100 // ms

  add(request: Request) {
    this.queue.push(request)

    if (this.queue.length >= this.batchSize) {
      this.flush()
    } else if (!this.timer) {
      this.timer = setTimeout(() => this.flush(), this.maxWaitTime)
    }
  }

  private async flush() {
    if (this.timer) {
      clearTimeout(this.timer)
      this.timer = null
    }

    if (this.queue.length === 0) return

    const batch = this.queue.splice(0)

    try {
      // Process batch efficiently
      const results = await processBatch(batch)

      // Deliver individual results
      for (let i = 0; i < batch.length; i++) {
        await deliverResult(batch[i].id, results[i])
      }
    } catch (error) {
      // Handle batch error
      for (const request of batch) {
        await deliverError(request.id, error)
      }
    }
  }
}

const batcher = new RequestBatcher()

on.ServiceRequest.created(async (request) => {
  if (request.batchable) {
    batcher.add(request)
  } else {
    await processImmediately(request)
  }
})

3. Async Processing

Use async for long-running tasks:

// Background job queue
import { queue } from 'sdk.do'

on.ServiceRequest.created(async (request) => {
  if (estimateProcessingTime(request) > 30000) {
    // Long-running task, use queue
    await queue.add(
      'service-execution',
      {
        requestId: request.id,
        serviceId: request.serviceId,
        inputs: request.inputs,
      },
      {
        priority: request.priority || 'normal',
        attempts: 3,
        backoff: 'exponential',
      }
    )

    // Acknowledge immediately
    send.ServiceRequest.acknowledged({
      requestId: request.id,
      message: 'Request queued for processing',
      estimatedTime: estimateProcessingTime(request),
    })
  } else {
    // Quick task, process synchronously
    await processImmediately(request)
  }
})

// Process background jobs
queue.process('service-execution', async (job) => {
  const { requestId, serviceId, inputs } = job.data

  try {
    const result = await executeService(serviceId, inputs)

    send.ServiceResult.deliver({
      requestId,
      outputs: result,
    })

    return result
  } catch (error) {
    if (job.attemptsMade < 3) {
      throw error // Will retry
    } else {
      send.ServiceRequest.fail({
        requestId,
        error: error.message,
        attempts: job.attemptsMade,
      })
    }
  }
})

Pricing Strategy

1. Value-Based Pricing

Price based on customer value:

// Calculate value-based price
async function calculatePrice(service: Service, request: ServiceRequest) {
  // Estimate value created
  const valueEstimate = await estimateValue(service, request)

  // Base price on value
  let price = valueEstimate.value * service.pricing.valueShare

  // Adjust for customer segment
  const customer = await db.Customers.findOne({ id: request.customerId })

  if (customer.segment === 'enterprise') {
    price *= 1.5 // Enterprise premium
  } else if (customer.segment === 'startup') {
    price *= 0.7 // Startup discount
  }

  // Volume discounts
  const monthlyUsage = await getMonthlyUsage(customer.id, service.id)

  if (monthlyUsage > 100) {
    price *= 0.9 // 10% volume discount
  }

  // Apply bounds
  price = Math.max(price, service.pricing.minimum)
  price = Math.min(price, service.pricing.maximum)

  return {
    price,
    factors: {
      baseValue: valueEstimate.value,
      valueShare: service.pricing.valueShare,
      customerSegment: customer.segment,
      volumeDiscount: monthlyUsage > 100,
      finalPrice: price,
    },
  }
}

2. Transparent Pricing

Always show customers what they'll pay:

// Price preview
on.ServiceRequest.created(async (request) => {
  // Calculate exact price
  const pricing = await calculatePrice(service, request)

  // Show breakdown to customer
  send.Customer.priceEstimate({
    customerId: request.customerId,
    requestId: request.id,
    estimate: {
      subtotal: pricing.price,
      breakdown: pricing.factors,
      tax: pricing.price * 0.08,
      total: pricing.price * 1.08,
      currency: 'USD',
    },
    requireApproval: pricing.price > 100,
  })

  // Wait for approval if needed
  if (pricing.price > 100) {
    const approved = await waitForApproval(request.id, 300000) // 5 minutes

    if (!approved) {
      send.ServiceRequest.cancel({
        requestId: request.id,
        reason: 'Customer did not approve price',
      })
      return
    }
  }

  // Process request...
})

3. Fair Billing

Only charge for successful deliveries:

// Success-based billing
on.ServiceResult.delivered(async (result) => {
  // Only charge if successful
  if (result.status === 'success') {
    send.Payment.charge({
      customerId: result.customerId,
      amount: result.cost,
      description: result.description,
    })
  }
})

// Refund on failure
on.ServiceRequest.fail(async (request) => {
  if (request.paymentId) {
    send.Payment.refund({
      paymentId: request.paymentId,
      reason: 'Service execution failed',
      amount: 'full',
    })
  }
})

// Partial refunds for quality issues
on.QualityIssue.reported(async (issue) => {
  if (issue.severity === 'major') {
    send.Payment.refund({
      paymentId: issue.paymentId,
      reason: 'Quality issue',
      amount: 'partial',
      percentage: 0.5, // 50% refund
    })
  }
})

Security

1. Input Sanitization

Protect against malicious input:

import { sanitize } from 'sdk.do'

function sanitizeInputs(inputs: any) {
  const sanitized = {}

  for (const [key, value] of Object.entries(inputs)) {
    if (typeof value === 'string') {
      // Remove dangerous characters
      sanitized[key] = sanitize.string(value, {
        allowedTags: [],
        maxLength: 10000,
      })
    } else if (typeof value === 'object') {
      sanitized[key] = sanitizeInputs(value)
    } else {
      sanitized[key] = value
    }
  }

  return sanitized
}

2. Rate Limiting

Prevent abuse:

import { rateLimit } from 'sdk.do'

// Rate limit configuration
const limiter = rateLimit({
  windowMs: 60000, // 1 minute
  max: 100, // 100 requests per minute
  keyGenerator: (request) => request.customerId,
  handler: async (request) => {
    send.ServiceRequest.reject({
      requestId: request.id,
      reason: 'Rate limit exceeded',
      retryAfter: 60,
    })
  },
})

on.ServiceRequest.created(async (request) => {
  // Check rate limit
  if (!(await limiter.check(request))) {
    return
  }

  // Process request...
})

3. Authentication & Authorization

Secure your services:

// Authenticate request
async function authenticate(request: ServiceRequest) {
  const token = request.headers['authorization']

  if (!token) {
    throw new Error('Missing authentication token')
  }

  const user = await verifyToken(token)

  if (!user) {
    throw new Error('Invalid authentication token')
  }

  return user
}

// Authorize access
async function authorize(user: User, service: Service, action: string) {
  // Check service access
  const hasAccess = await db.ServiceAccess.exists({
    userId: user.id,
    serviceId: service.id,
    action,
  })

  if (!hasAccess) {
    throw new Error('Unauthorized access to service')
  }

  // Check subscription status
  if (service.requiresSubscription) {
    const subscription = await db.Subscriptions.findOne({
      userId: user.id,
      serviceId: service.id,
      status: 'active',
    })

    if (!subscription) {
      throw new Error('Active subscription required')
    }
  }

  return true
}

Monitoring & Observability

1. Structured Logging

Log everything important:

import { logger } from 'sdk.do'

// Structured logging with context
on.ServiceRequest.created(async (request) => {
  const context = {
    requestId: request.id,
    serviceId: request.serviceId,
    customerId: request.customerId,
    timestamp: new Date().toISOString(),
  }

  logger.info('request.start', context)

  try {
    const result = await executeService(request)

    logger.info('request.success', {
      ...context,
      duration: result.duration,
      cost: result.cost,
    })
  } catch (error) {
    logger.error('request.failed', {
      ...context,
      error: error.message,
      stack: error.stack,
    })
  }
})

2. Comprehensive Metrics

Track everything:

// Key metrics to track
const metrics = {
  // Performance
  'service.response_time': 'histogram',
  'service.throughput': 'counter',
  'service.error_rate': 'gauge',

  // Business
  'service.revenue': 'counter',
  'service.customers': 'gauge',
  'service.conversions': 'counter',

  // Quality
  'service.quality_score': 'gauge',
  'service.customer_satisfaction': 'gauge',

  // Infrastructure
  'service.cpu_usage': 'gauge',
  'service.memory_usage': 'gauge',
  'service.active_requests': 'gauge',
}

3. Proactive Alerting

Catch issues early:

// Alert on anomalies
const anomalyDetector = {
  check: async (metric: string, value: number) => {
    const historical = await getHistoricalData(metric, '7d')
    const mean = calculateMean(historical)
    const stdDev = calculateStdDev(historical)

    // Check if value is anomalous (> 3 std devs)
    if (Math.abs(value - mean) > 3 * stdDev) {
      send.Alert.create({
        severity: 'warning',
        title: `Anomaly detected: ${metric}`,
        value,
        expected: mean,
        deviation: Math.abs(value - mean) / stdDev,
      })
    }
  },
}

Documentation

1. API Documentation

Document everything:

const service = await $.Service.create({
  name: 'Document Summarizer',

  documentation: {
    description: 'AI-powered document summarization service',

    examples: [
      {
        title: 'Basic usage',
        request: {
          document: 'Long document text...',
          maxLength: 500,
        },
        response: {
          summary: 'Concise summary...',
          keyPoints: ['Point 1', 'Point 2'],
          confidence: 0.95,
        },
      },
    ],

    errors: [
      {
        code: 'DOCUMENT_TOO_SHORT',
        message: 'Document must be at least 100 words',
        resolution: 'Provide a longer document',
      },
      {
        code: 'INVALID_STYLE',
        message: 'Invalid summary style',
        resolution: 'Use one of: concise, detailed, bullet-points',
      },
    ],

    rateLimit: '100 requests per minute',
    pricing: '$0.01 per 100 words',
    averageResponseTime: '5 seconds',
  },
})

2. User Guides

Help customers succeed:

  • Clear onboarding
  • Step-by-step tutorials
  • Common use cases
  • Troubleshooting guides
  • Best practices

3. Changelog

Track changes:

const changelog = [
  {
    version: '1.2.0',
    date: '2025-10-25',
    changes: ['Added support for PDF documents', 'Improved summary quality by 15%', 'Fixed issue with long documents'],
  },
  {
    version: '1.1.0',
    date: '2025-10-15',
    changes: ['Added bullet-point summary style', 'Reduced average response time by 20%'],
  },
]

Summary

Key principles for successful services:

  1. Focus: Do one thing exceptionally well
  2. Quality: Validate inputs, verify outputs
  3. Performance: Cache, batch, async
  4. Pricing: Fair, transparent, value-based
  5. Security: Sanitize, limit, authenticate
  6. Monitoring: Log, measure, alert
  7. Documentation: Clear, comprehensive, current

Next Steps