> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ollie.shop/llms.txt
> Use this file to discover all available pages before exploring further.

# Best Practices

> Write secure, maintainable, and performant functions. Learn proven patterns for error handling, security, testing, and scalable architecture.

{/* 
Best Practices Keywords: security practices, performance optimization, error handling, maintainability, code quality, testing strategies, scalability patterns

Core Development Principles:
1. Security First
 - Input validation and sanitization
 - Environment variable protection
 - Authentication and authorization
 - Secure external API communication
 - Data privacy and compliance

2. Performance Optimization
 - Minimize cold start times
 - Efficient memory usage
 - Optimal dependency management
 - Strategic caching implementation
 - Response time optimization

3. Maintainability
 - Clean, readable code structure
 - Comprehensive documentation
 - Consistent coding standards
 - Version control best practices
 - Code review processes

4. Reliability
 - Robust error handling
 - Graceful degradation
 - Retry logic for transient failures
 - Monitoring and alerting
 - Testing coverage

Security Best Practices:
1. Input Validation
 - Validate all incoming data
 - Sanitize user inputs
 - Use TypeScript for type safety
 - Implement schema validation (Zod, Joi)
 - Prevent injection attacks

2. Environment Variables
 - Never hardcode sensitive data
 - Use environment variables for secrets
 - Validate environment variable presence
 - Use different values for dev/prod
 - Document required variables

3. Authentication and Authorization
 - Implement proper auth checks
 - Use JWT tokens securely
 - Validate user permissions
 - Handle auth failures gracefully
 - Log security events

4. External API Security
 - Use HTTPS for all external calls
 - Validate SSL certificates
 - Implement API rate limiting
 - Handle API key security
 - Monitor for suspicious activity

Performance Optimization:
1. Cold Start Reduction
 - Minimize package dependencies
 - Use dynamic imports selectively
 - Optimize initialization code
 - Reduce bundle size
 - Cache global objects appropriately

2. Runtime Performance
 - Use efficient algorithms
 - Minimize external API calls
 - Implement appropriate caching
 - Use streams for large data
 - Optimize JSON parsing/serialization

3. Memory Management
 - Avoid memory leaks
 - Clean up resources
 - Use appropriate data structures
 - Monitor memory usage
 - Handle large payloads efficiently

4. Network Optimization
 - Batch API requests when possible
 - Use connection pooling
 - Implement request timeouts
 - Handle network failures gracefully
 - Minimize payload sizes

Error Handling Patterns:
1. Structured Error Handling
 - Use try-catch blocks consistently
 - Create custom error types
 - Include relevant context
 - Log errors with sufficient detail
 - Return meaningful error messages

2. HTTP Status Codes
 - Use appropriate status codes
 - 400: Bad Request (client errors)
 - 401: Unauthorized (auth required)
 - 403: Forbidden (insufficient permissions)
 - 500: Internal Server Error (server errors)

3. Graceful Degradation
 - Handle external service failures
 - Provide fallback responses
 - Cache responses when appropriate
 - Implement circuit breaker patterns
 - Maintain service availability

4. Error Recovery
 - Implement retry logic
 - Use exponential backoff
 - Set appropriate timeout values
 - Handle transient failures
 - Log retry attempts

Code Quality Standards:
1. TypeScript Usage
 - Use strict TypeScript configuration
 - Define clear interfaces and types
 - Avoid 'any' type when possible
 - Use generics for reusable code
 - Document complex types

2. Code Organization
 - Separate concerns properly
 - Use meaningful function names
 - Keep functions focused and small
 - Group related functionality
 - Maintain consistent file structure

3. Documentation
 - Document complex business logic
 - Use JSDoc for function documentation
 - Maintain README files
 - Document API contracts
 - Include usage examples

4. Version Control
 - Use meaningful commit messages
 - Create feature branches
 - Conduct code reviews
 - Tag releases appropriately
 - Maintain clean commit history

Testing Strategies:
1. Unit Testing
 - Test individual functions
 - Mock external dependencies
 - Test edge cases and error conditions
 - Achieve high test coverage
 - Use descriptive test names

2. Integration Testing
 - Test complete workflows
 - Use realistic test data
 - Test error scenarios
 - Validate external integrations
 - Test performance under load

3. Test Data Management
 - Use factories for test data
 - Isolate tests from each other
 - Clean up test resources
 - Use appropriate test databases
 - Avoid hardcoded test values

Hub Integration Best Practices:
1. Request Function Patterns
 - Validate incoming requests
 - Handle different HTTP methods
 - Return consistent response formats
 - Implement proper logging
 - Use middleware patterns

2. Response Function Patterns
 - Keep processing lightweight
 - Handle async operations properly
 - Log important events
 - Don't affect user response time
 - Implement error recovery

3. Task Function Patterns
 - Design for idempotency
 - Handle long-running operations
 - Implement proper scheduling
 - Monitor execution success
 - Use appropriate error handling

Monitoring and Observability:
1. Logging
 - Log important business events
 - Include relevant context
 - Use structured logging
 - Monitor error rates
 - Track performance metrics

2. Metrics and Alerts
 - Monitor function execution time
 - Track error rates and types
 - Set up alerts for critical issues
 - Monitor resource usage
 - Track business metrics

3. Debugging
 - Include correlation IDs
 - Log request/response data
 - Monitor external API calls
 - Track user journeys
 - Use distributed tracing

Deployment Best Practices:
1. Pre-deployment Checks
 - Run all tests before deployment
 - Verify environment variables
 - Check dependency versions
 - Review code changes
 - Test in staging environment

2. Deployment Strategy
 - Use gradual rollouts
 - Monitor deployment health
 - Have rollback plans ready
 - Test after deployment
 - Update documentation

3. Post-deployment
 - Monitor function performance
 - Check error rates
 - Validate business metrics
 - Update team on changes
 - Document lessons learned

Common Anti-patterns to Avoid:
- Hardcoding sensitive data
- Ignoring error conditions
- Using synchronous operations for I/O
- Creating memory leaks
- Not validating inputs
- Poor error messages
- Inconsistent response formats
- Blocking operations in response functions
- Not monitoring function health

Related Concepts: security practices, performance optimization, error handling, testing strategies, deployment patterns, monitoring, code quality
*/}

Leverage these proven patterns and best practices to build production-ready functions that are secure, performant, and maintainable.

<CardGroup cols={2}>
  <Card title="Code Quality" icon="code">
    * Follow consistent naming conventions
    * Implement proper error handling
    * Use TypeScript for better type safety
    * Keep functions focused and small
  </Card>

  <Card title="Security & Performance" icon="shield">
    * Validate all input data
    * Use environment variables for secrets
    * Implement proper authentication
    * Optimize for cold start performance
  </Card>
</CardGroup>

## Request Function Patterns

### HTTP Method Handling

<CodeGroup>
  ```typescript title="REST API Handler" icon="globe" lines theme={"system"}
  export const handler = async (event) => {
    const { httpMethod, body } = event;
    const data = body ? JSON.parse(body) : {};
    
    switch (httpMethod) {
      case 'GET':
        return {
          statusCode: 200,
          body: JSON.stringify({ users: await getUsers() })
        };
        
      case 'POST':
        const newUser = await createUser(data);
        return {
          statusCode: 201,
          body: JSON.stringify({ id: newUser.id, message: 'User created' })
        };
        
      case 'PUT':
        const updatedUser = await updateUser(data);
        return {
          statusCode: 200,
          body: JSON.stringify(updatedUser)
        };
        
      case 'DELETE':
        await deleteUser(data.id);
        return {
          statusCode: 204,
          body: ''
        };
        
      default:
        return {
          statusCode: 405,
          body: JSON.stringify({ error: 'Method not allowed' })
        };
    }
  };
  ```

  ```json title="Example Request" icon="arrow-right" theme={"system"}
  {
    "httpMethod": "POST",
    "body": "{\"name\":\"John Doe\",\"email\":\"john@example.com\"}"
  }
  ```

  ```json title="Success Response" icon="check-circle" theme={"system"}
  {
    "statusCode": 201,
    "body": "{\"id\":\"user_123\",\"message\":\"User created\"}"
  }
  ```
</CodeGroup>

### Input Validation

<CodeGroup>
  ```typescript title="Validation Logic" icon="shield-check" lines theme={"system"}
  export const handler = async (event) => {
    const { body } = event;
    
    try {
      const data = JSON.parse(body || '{}');
      
      // Validate required fields
      const errors = [];
      if (!data.email) errors.push('Email is required');
      if (!data.password) errors.push('Password is required');
      if (data.password && data.password.length < 8) {
        errors.push('Password must be at least 8 characters');
      }
      
      // Return validation errors
      if (errors.length > 0) {
        return {
          statusCode: 400,
          body: JSON.stringify({ 
            error: 'Validation failed',
            details: errors 
          })
        };
      }
      
      // Process valid data
      const result = await processUser(data);
      return {
        statusCode: 200,
        body: JSON.stringify(result)
      };
    } catch (error) {
      return {
        statusCode: 400,
        body: JSON.stringify({ error: 'Invalid JSON' })
      };
    }
  };
  ```

  ```json title="Invalid Input" icon="x-circle" theme={"system"}
  {
    "email": "",
    "password": "123"
  }
  ```

  ```json title="Validation Error Response" icon="exclamation-triangle" theme={"system"}
  {
    "statusCode": 400,
    "body": {
      "error": "Validation failed",
      "details": [
        "Email is required",
        "Password must be at least 8 characters"
      ]
    }
  }
  ```
</CodeGroup>

### Error Handling

<CodeGroup>
  ```typescript title="Error Handler" icon="exclamation-triangle" lines theme={"system"}
  export const handler = async (event) => {
    try {
      const result = await processRequest(event);
      return {
        statusCode: 200,
        body: JSON.stringify({ success: true, data: result })
      };
    } catch (error) {
      console.error('Request processing error:', error);
      
      // Handle validation errors
      if (error.name === 'ValidationError') {
        return {
          statusCode: 400,
          body: JSON.stringify({ 
            error: 'Invalid input',
            details: error.message 
          })
        };
      }
      
      // Handle not found errors
      if (error.name === 'NotFoundError') {
        return {
          statusCode: 404,
          body: JSON.stringify({ error: 'Resource not found' })
        };
      }
      
      // Handle unexpected errors
      return {
        statusCode: 500,
        body: JSON.stringify({ 
          error: 'Internal server error',
          requestId: event.requestContext?.requestId
        })
      };
    }
  };
  ```

  ```json title="Error Types" icon="list" theme={"system"}
  {
    "ValidationError": "400 - Bad Request",
    "NotFoundError": "404 - Not Found", 
    "AuthenticationError": "401 - Unauthorized",
    "PermissionError": "403 - Forbidden",
    "RateLimitError": "429 - Too Many Requests",
    "UnexpectedError": "500 - Internal Server Error"
  }
  ```

  ```json title="Error Response Format" icon="alert-triangle" theme={"system"}
  {
    "error": "Error description",
    "details": "Additional error details",
    "requestId": "req_123456789",
    "timestamp": "2024-01-12T10:30:45.123Z"
  }
  ```
</CodeGroup>

## Security Best Practices

### Authentication & Authorization

<CodeGroup>
  ```typescript title="JWT Validation" icon="key" lines theme={"system"}
  import jwt from 'jsonwebtoken';

  export const handler = async (event) => {
    try {
      // Extract token from header
      const authHeader = event.headers.Authorization || event.headers.authorization;
      if (!authHeader?.startsWith('Bearer ')) {
        return {
          statusCode: 401,
          body: JSON.stringify({ error: 'Missing or invalid authorization header' })
        };
      }
      
      const token = authHeader.substring(7);
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      
      // Check user permissions
      if (!decoded.permissions?.includes('admin')) {
        return {
          statusCode: 403,
          body: JSON.stringify({ error: 'Insufficient permissions' })
        };
      }
      
      // Continue with authenticated request
      const result = await processAuthenticatedRequest(decoded, event);
      return {
        statusCode: 200,
        body: JSON.stringify(result)
      };
    } catch (error) {
      return {
        statusCode: 401,
        body: JSON.stringify({ error: 'Invalid token' })
      };
    }
  };
  ```

  ```typescript title="Input Sanitization" icon="shield" lines theme={"system"}
  import validator from 'validator';

  export const sanitizeInput = (data) => {
    return {
      email: validator.isEmail(data.email) ? validator.normalizeEmail(data.email) : null,
      name: validator.escape(data.name || '').trim(),
      phone: validator.isMobilePhone(data.phone) ? data.phone : null,
      url: validator.isURL(data.url) ? data.url : null
    };
  };

  export const handler = async (event) => {
    const rawData = JSON.parse(event.body || '{}');
    const sanitizedData = sanitizeInput(rawData);
    
    // Validate sanitized data
    if (!sanitizedData.email) {
      return {
        statusCode: 400,
        body: JSON.stringify({ error: 'Valid email is required' })
      };
    }
    
    // Process with clean data
    const result = await processUser(sanitizedData);
    return {
      statusCode: 200,
      body: JSON.stringify(result)
    };
  };
  ```
</CodeGroup>

### Environment Variables & Secrets

<CodeGroup>
  ```typescript title="Secure Configuration" icon="key" lines theme={"system"}
  // Use environment variables for sensitive data
  const config = {
    database: {
      host: process.env.DB_HOST,
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      ssl: process.env.NODE_ENV === 'production'
    },
    jwt: {
      secret: process.env.JWT_SECRET,
      expiresIn: process.env.JWT_EXPIRES_IN || '24h'
    },
    external: {
      apiKey: process.env.EXTERNAL_API_KEY,
      webhookSecret: process.env.WEBHOOK_SECRET
    }
  };

  // Validate required environment variables
  const requiredEnvVars = ['DB_HOST', 'JWT_SECRET', 'EXTERNAL_API_KEY'];
  const missingVars = requiredEnvVars.filter(varName => !process.env[varName]);

  if (missingVars.length > 0) {
    throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
  }
  ```

  ```typescript title="Rate Limiting" icon="clock" lines theme={"system"}
  const rateLimiter = new Map();

  export const checkRateLimit = (clientId: string, limit = 100, windowMs = 60000) => {
    const now = Date.now();
    const clientData = rateLimiter.get(clientId) || { requests: 0, resetTime: now + windowMs };
    
    // Reset if window expired
    if (now > clientData.resetTime) {
      clientData.requests = 0;
      clientData.resetTime = now + windowMs;
    }
    
    clientData.requests++;
    rateLimiter.set(clientId, clientData);
    
    return {
      allowed: clientData.requests <= limit,
      remaining: Math.max(0, limit - clientData.requests),
      resetTime: clientData.resetTime
    };
  };

  export const handler = async (event) => {
    const clientId = event.requestContext.identity.sourceIp;
    const rateLimit = checkRateLimit(clientId);
    
    if (!rateLimit.allowed) {
      return {
        statusCode: 429,
        headers: {
          'X-RateLimit-Remaining': rateLimit.remaining.toString(),
          'X-RateLimit-Reset': rateLimit.resetTime.toString()
        },
        body: JSON.stringify({ error: 'Rate limit exceeded' })
      };
    }
    
    // Process request
    const result = await processRequest(event);
    return {
      statusCode: 200,
      headers: {
        'X-RateLimit-Remaining': rateLimit.remaining.toString()
      },
      body: JSON.stringify(result)
    };
  };
  ```
</CodeGroup>

## Performance Optimization

### Cold Start Optimization

<CodeGroup>
  ```typescript title="Module Initialization" icon="zap" lines theme={"system"}
  // Initialize outside handler for reuse across invocations
  import { createConnection } from './database';
  import { initializeCache } from './cache';

  let dbConnection;
  let cache;

  // Initialize on first import
  const initializeResources = async () => {
    if (!dbConnection) {
      dbConnection = await createConnection();
    }
    if (!cache) {
      cache = await initializeCache();
    }
  };

  export const handler = async (event) => {
    // Ensure resources are initialized
    await initializeResources();
    
    // Use cached resources
    const result = await dbConnection.query('SELECT * FROM users');
    await cache.set('users', result, 300); // Cache for 5 minutes
    
    return {
      statusCode: 200,
      body: JSON.stringify(result)
    };
  };
  ```

  ```typescript title="Response Caching" icon="database" lines theme={"system"}
  const responseCache = new Map();

  export const handler = async (event) => {
    const cacheKey = `${event.httpMethod}:${event.path}:${JSON.stringify(event.queryStringParameters)}`;
    const cachedResponse = responseCache.get(cacheKey);
    
    // Return cached response if available and not expired
    if (cachedResponse && cachedResponse.expiresAt > Date.now()) {
      return {
        statusCode: 200,
        headers: {
          'Content-Type': 'application/json',
          'X-Cache': 'HIT'
        },
        body: JSON.stringify(cachedResponse.data)
      };
    }
    
    // Process request and cache result
    const result = await processRequest(event);
    responseCache.set(cacheKey, {
      data: result,
      expiresAt: Date.now() + (5 * 60 * 1000) // 5 minutes
    });
    
    return {
      statusCode: 200,
      headers: {
        'Content-Type': 'application/json',
        'X-Cache': 'MISS'
      },
      body: JSON.stringify(result)
    };
  };
  ```
</CodeGroup>

### Database Optimization

<CodeGroup>
  ```typescript title="Connection Pooling" icon="database" lines theme={"system"}
  import { Pool } from 'pg';

  // Create connection pool outside handler
  const pool = new Pool({
    host: process.env.DB_HOST,
    database: process.env.DB_NAME,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    max: 10, // Maximum pool size
    idleTimeoutMillis: 30000,
    connectionTimeoutMillis: 2000,
  });

  export const handler = async (event) => {
    const client = await pool.connect();
    
    try {
      // Use parameterized queries to prevent SQL injection
      const result = await client.query(
        'SELECT * FROM users WHERE email = $1 AND status = $2',
        [event.body.email, 'active']
      );
      
      return {
        statusCode: 200,
        body: JSON.stringify(result.rows)
      };
    } finally {
      client.release(); // Always release the client back to pool
    }
  };
  ```

  ```typescript title="Batch Operations" icon="layers" lines theme={"system"}
  export const handler = async (event) => {
    const { operations } = JSON.parse(event.body);
    
    // Process operations in batches to avoid overwhelming the database
    const batchSize = 10;
    const results = [];
    
    for (let i = 0; i < operations.length; i += batchSize) {
      const batch = operations.slice(i, i + batchSize);
      
      // Process batch concurrently
      const batchPromises = batch.map(async (operation) => {
        try {
          return await processOperation(operation);
        } catch (error) {
          return { error: error.message, operation: operation.id };
        }
      });
      
      const batchResults = await Promise.allSettled(batchPromises);
      results.push(...batchResults.map(result => 
        result.status === 'fulfilled' ? result.value : result.reason
      ));
    }
    
    return {
      statusCode: 200,
      body: JSON.stringify({
        processed: results.length,
        results
      })
    };
  };
  ```
</CodeGroup>

## Testing Best Practices

### Unit Testing

<CodeGroup>
  ```typescript title="Function Testing" icon="test-tube" lines theme={"system"}
  import { handler } from '../src/user-handler';

  describe('User Handler', () => {
    test('should create user with valid data', async () => {
      // Arrange
      const event = {
        httpMethod: 'POST',
        body: JSON.stringify({
          name: 'John Doe',
          email: 'john@example.com',
          password: 'securePassword123'
        })
      };
      
      // Act
      const response = await handler(event);
      const body = JSON.parse(response.body);
      
      // Assert
      expect(response.statusCode).toBe(201);
      expect(body).toHaveProperty('id');
      expect(body.message).toBe('User created');
    });
    
    test('should return validation error for invalid email', async () => {
      // Arrange
      const event = {
        httpMethod: 'POST',
        body: JSON.stringify({
          name: 'John Doe',
          email: 'invalid-email',
          password: 'securePassword123'
        })
      };
      
      // Act
      const response = await handler(event);
      const body = JSON.parse(response.body);
      
      // Assert
      expect(response.statusCode).toBe(400);
      expect(body.error).toBe('Validation failed');
      expect(body.details).toContain('Valid email is required');
    });
  });
  ```

  ```typescript title="Mock External Services" icon="webhook" lines theme={"system"}
  import { jest } from '@jest/globals';
  import { handler } from '../src/payment-handler';

  // Mock external payment service
  jest.mock('../src/services/payment-service', () => ({
    processPayment: jest.fn(),
    refundPayment: jest.fn()
  }));

  import { processPayment } from '../src/services/payment-service';

  describe('Payment Handler', () => {
    beforeEach(() => {
      jest.clearAllMocks();
    });
    
    test('should process payment successfully', async () => {
      // Arrange
      (processPayment as jest.Mock).mockResolvedValue({
        id: 'pay_123',
        status: 'succeeded',
        amount: 1999
      });
      
      const event = {
        body: JSON.stringify({
          amount: 1999,
          currency: 'usd',
          paymentMethod: 'card_123'
        })
      };
      
      // Act
      const response = await handler(event);
      const body = JSON.parse(response.body);
      
      // Assert
      expect(response.statusCode).toBe(200);
      expect(body.paymentId).toBe('pay_123');
      expect(processPayment).toHaveBeenCalledWith({
        amount: 1999,
        currency: 'usd',
        paymentMethod: 'card_123'
      });
    });
  });
  ```
</CodeGroup>

## Response Function Patterns

### Conditional Enhancement

<CodeGroup>
  ```typescript title="Conditional Logic" icon="filter" lines theme={"system"}
  export const handler = async (event) => {
    const { request, response } = event;
    const responseBody = JSON.parse(response.body);
    
    // Only enhance specific endpoints
    if (request.path.includes('/api/')) {
      // Add API-specific enhancements
      return {
        ...response,
        headers: {
          ...response.headers,
          'X-API-Version': '1.0',
          'X-Rate-Limit': '1000'
        },
        body: JSON.stringify({
          ...responseBody,
          meta: {
            version: '1.0',
            timestamp: new Date().toISOString()
          }
        })
      };
    }
    
    return response; // Return unchanged for other endpoints
  };
  ```

  ```typescript title="Error Enhancement" icon="exclamation-triangle" lines theme={"system"}
  export const handler = async (event) => {
    const { request, response } = event;
    
    // Enhance error responses with helpful information
    if (response.statusCode >= 400) {
      const errorBody = JSON.parse(response.body);
      
      return {
        ...response,
        headers: {
          ...response.headers,
          'X-Error-ID': generateErrorId(),
          'X-Support-Contact': 'support@myapp.com'
        },
        body: JSON.stringify({
          ...errorBody,
          support: {
            documentation: 'https://docs.myapp.com',
            contact: 'support@myapp.com',
            statusPage: 'https://status.myapp.com'
          },
          requestId: request.requestContext?.requestId
        })
      };
    }
    
    return response;
  };
  ```

  ```typescript title="Performance Optimization" icon="zap" lines theme={"system"}
  export const handler = async (event) => {
    const { request, response } = event;
    const responseBody = JSON.parse(response.body);
    
    // Add performance optimizations
    const optimizedResponse = {
      ...response,
      headers: {
        ...response.headers,
        // Compression
        'Content-Encoding': 'gzip',
        
        // Caching based on content type
        'Cache-Control': request.path.includes('/static/') 
          ? 'public, max-age=31536000' // 1 year for static
          : 'public, max-age=300',     // 5 minutes for dynamic
        
        // Performance hints
        'X-Response-Time': Date.now() - request.startTime,
        'X-Content-Length': JSON.stringify(responseBody).length
      }
    };
    
    return optimizedResponse;
  };
  ```
</CodeGroup>

## Task Function Patterns

### Error Handling and Retries

<CodeGroup>
  ```typescript title="Retry Logic" icon="refresh" lines theme={"system"}
  export const handler = async (event) => {
    const maxRetries = 3;
    let attempt = 0;
    
    while (attempt < maxRetries) {
      try {
        const result = await performTask();
        return {
          statusCode: 200,
          body: JSON.stringify({
            success: true,
            attempt: attempt + 1,
            result
          })
        };
      } catch (error) {
        attempt++;
        console.error(`Task attempt ${attempt} failed:`, error);
        
        if (attempt >= maxRetries) {
          // Send notification on final failure
          await sendTaskFailureNotification(error);
          
          return {
            statusCode: 500,
            body: JSON.stringify({
              error: 'Task failed after maximum retries',
              attempts: attempt,
              lastError: error.message
            })
          };
        }
        
        // Wait before retrying (exponential backoff)
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
      }
    }
  };
  ```

  ```typescript title="Batch Processing" icon="layers" lines theme={"system"}
  export const handler = async (event) => {
    try {
      const items = await getItemsToProcess();
      const batchSize = 50;
      const results = [];
      
      for (let i = 0; i < items.length; i += batchSize) {
        const batch = items.slice(i, i + batchSize);
        console.log(`Processing batch ${Math.floor(i/batchSize) + 1}/${Math.ceil(items.length/batchSize)}`);
        
        const batchResults = await Promise.allSettled(
          batch.map(item => processItem(item))
        );
        
        results.push(...batchResults);
        
        // Brief pause between batches
        if (i + batchSize < items.length) {
          await new Promise(resolve => setTimeout(resolve, 100));
        }
      }
      
      const successful = results.filter(r => r.status === 'fulfilled').length;
      const failed = results.filter(r => r.status === 'rejected').length;
      
      return {
        statusCode: 200,
        body: JSON.stringify({
          message: 'Batch processing completed',
          total: items.length,
          successful,
          failed,
          batches: Math.ceil(items.length / batchSize)
        })
      };
    } catch (error) {
      return {
        statusCode: 500,
        body: JSON.stringify({ error: error.message })
      };
    }
  };
  ```

  ```typescript title="Progress Tracking" icon="chart-line" lines theme={"system"}
  export const handler = async (event) => {
    const taskId = `task-${Date.now()}`;
    
    try {
      // Initialize progress tracking
      await updateTaskProgress(taskId, { status: 'started', progress: 0 });
      
      const items = await getItemsToProcess();
      const totalItems = items.length;
      
      for (let i = 0; i < items.length; i++) {
        await processItem(items[i]);
        
        // Update progress every 10 items or at the end
        if ((i + 1) % 10 === 0 || i === items.length - 1) {
          const progress = Math.round(((i + 1) / totalItems) * 100);
          await updateTaskProgress(taskId, {
            status: 'running',
            progress,
            processed: i + 1,
            total: totalItems
          });
        }
      }
      
      // Mark as completed
      await updateTaskProgress(taskId, {
        status: 'completed',
        progress: 100,
        processed: totalItems,
        total: totalItems,
        completedAt: new Date().toISOString()
      });
      
      return {
        statusCode: 200,
        body: JSON.stringify({
          taskId,
          message: 'Task completed successfully',
          processed: totalItems
        })
      };
    } catch (error) {
      await updateTaskProgress(taskId, {
        status: 'failed',
        error: error.message,
        failedAt: new Date().toISOString()
      });
      
      throw error;
    }
  };
  ```
</CodeGroup>

### Schedule Formats

<CodeGroup>
  ```typescript title="Cron Expressions" icon="clock" lines theme={"system"}
  // Every day at 2:30 AM
  cron(30 2 * * ? *)

  // Every weekday at 9:00 AM
  cron(0 9 ? * MON-FRI *)

  // Every 15 minutes
  cron(*/15 * * * ? *)

  // First day of every month at midnight
  cron(0 0 1 * ? *)

  // Every Sunday at 6:00 PM
  cron(0 18 ? * SUN *)
  ```

  ```typescript title="Rate Expressions" icon="timer" lines theme={"system"}
  // Every 5 minutes
  rate(5 minutes)

  // Every hour
  rate(1 hour)

  // Every 2 days
  rate(2 days)

  // Every 30 seconds
  rate(30 seconds)
  ```

  ```json title="Schedule Examples" icon="calendar" theme={"system"}
  {
    "dailyReports": "cron(0 8 * * ? *)",
    "weeklyCleanup": "cron(0 2 ? * SUN *)",
    "monthlyBilling": "cron(0 0 1 * ? *)",
    "frequentSync": "rate(5 minutes)",
    "healthCheck": "rate(30 seconds)"
  }
  ```
</CodeGroup>

## General Development Tips

<CardGroup cols={2}>
  <Card title="Function Design" icon="code">
    * Keep functions small and focused
    * Use TypeScript for better developer experience
    * Follow single responsibility principle
    * Return consistent response formats
  </Card>

  <Card title="Error Handling" icon="exclamation-triangle">
    * Always use try-catch blocks
    * Return appropriate HTTP status codes
    * Log errors for debugging
    * Provide helpful error messages
  </Card>

  <Card title="Performance" icon="zap">
    * Initialize resources outside the handler
    * Use connection pooling for databases
    * Implement caching where appropriate
    * Batch operations when possible
  </Card>

  <Card title="Security" icon="shield">
    * Validate and sanitize all inputs
    * Use environment variables for secrets
    * Implement authentication and authorization
    * Add rate limiting to prevent abuse
  </Card>
</CardGroup>

### Response Function Guidelines

<CardGroup cols={2}>
  <Card title="Fail Gracefully" icon="shield">
    Always return the original response if your enhancement fails. Don't break the user experience.
  </Card>

  <Card title="Keep It Fast" icon="zap">
    Response functions should be lightweight. Heavy processing can slow down responses.
  </Card>

  <Card title="Be Selective" icon="target">
    Not every response needs enhancement. Use conditional logic to enhance only when needed.
  </Card>

  <Card title="Log Errors" icon="bug">
    Log enhancement errors for debugging, but don't let them affect the user's response.
  </Card>
</CardGroup>

### Task Function Guidelines

<CardGroup cols={2}>
  <Card title="Keep Tasks Idempotent" icon="refresh">
    Design tasks to handle being run multiple times safely. Check for existing work before processing.
  </Card>

  <Card title="Process in Batches" icon="layers">
    For large datasets, process items in small batches to avoid timeouts and memory issues.
  </Card>

  <Card title="Monitor and Alert" icon="bell">
    Set up monitoring for task failures and send notifications when critical tasks fail.
  </Card>

  <Card title="Handle Failures Gracefully" icon="shield">
    Implement retry logic with exponential backoff. Store failed items for manual review.
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={3}>
  <Card title="Local Development" icon="code" href="/ollie-hub/development/local-development">
    Set up your development environment
  </Card>

  <Card title="Deployment" icon="rocket" href="/ollie-hub/development/deployment">
    Deploy your functions to production
  </Card>

  <Card title="Environment Variables" icon="key" href="/ollie-hub/development/environment-variables">
    Manage configuration and secrets
  </Card>
</CardGroup>

<Info>
  **Pro Tip:** Start with simple patterns and gradually add complexity. Focus on getting the core functionality working before optimizing for performance.
</Info>
