Mirra
Mirra APIScripts

Script Technical Notes

This page covers advanced topics for script development including configuration options, execution limits, version control, and troubleshooting.

Configuration Options

Scripts accept configuration parameters that control execution behavior, resource access, and cost limits.

Runtime

runtime

Execution environment. Must be "nodejs18" or "python3.11". Default: "nodejs18".

{
  "runtime": "nodejs18"
}

Timeout

timeout

Maximum execution time in seconds. Range: 1-300. Default: 30. Scripts exceeding this limit are terminated.

{
  "config": {
    "timeout": 60
  }
}

Memory

memory

Memory allocation in MB. Range: 128-3008. Default: 128. Higher memory allocation provides proportionally more CPU.

{
  "config": {
    "memory": 512
  }
}

Max Cost Per Execution

maxCostPerExecution

Maximum cost per execution in USD. Default: 1.0. Executions exceeding this limit fail with a cost limit error.

{
  "config": {
    "maxCostPerExecution": 5.0
  }
}

Max Executions Per Day

maxExecutionsPerDay

Maximum executions per 24-hour period. Default: 100. Scripts stop executing when this limit is reached until the next day.

{
  "config": {
    "maxExecutionsPerDay": 1000
  }
}

Allowed Resources

allowedResources

Array of resource IDs the script can access. Empty array (default) denies all resource access. See Resources for details.

{
  "config": {
    "allowedResources": ["resource_123", "resource_456"]
  }
}

Execution Limits

Platform Limits

  • Maximum execution time: 300 seconds (5 minutes)
  • Maximum memory: 3008 MB
  • Maximum code size: 50 MB (including dependencies)
  • Maximum response size: 6 MB
  • Concurrent executions: 10 per script

Rate Limits

  • Manual executions: 100 per minute
  • Event-triggered executions: No limit (subject to cost controls)
  • Cron executions: Based on cron schedule configuration

Cost Controls

Scripts automatically stop executing when cost limits are reached:

  • Per-execution limit: Configurable via maxCostPerExecution
  • Daily limit: Configurable via maxExecutionsPerDay
  • Monthly budget: Set at account level

Version Control

Scripts maintain multiple versions, enabling safe deployments and rollbacks. Each version is immutable once created.

Creating Versions

POST /api/sdk/v1/scripts/{scriptId}/versions
{
  "code": "export async function handler(event) { ... }",
  "version": "1.1.0",
  "changelog": "Added error handling"
}

Version Naming

Follow semantic versioning (MAJOR.MINOR.PATCH):

  • MAJOR: Breaking changes to event structure or return format
  • MINOR: New features, backward compatible
  • PATCH: Bug fixes, no API changes

Examples:

  • 1.0.0 - Initial release
  • 1.1.0 - Added new feature
  • 1.1.1 - Fixed bug
  • 2.0.0 - Breaking change

Deploying Versions

POST /api/sdk/v1/scripts/{scriptId}/deploy
{
  "versionId": "version_456"
}

Deployments reference a specific version number, creating a new function deployment with that version's code. Only one version can be deployed at a time.

Rollback

To rollback to a previous version, deploy that version:

POST /api/sdk/v1/scripts/{scriptId}/deploy
{
  "versionId": "version_123"  // Previous stable version
}

Marketplace Publishing

Scripts can be published to the Mirra marketplace with pricing models.

Publishing Requirements

  • Script successfully deployed with working code
  • Complete metadata (name, description, tags)
  • Valid pricing configuration
  • Tested execution with no errors

Pricing Models

Free

{
  "pricing": {
    "model": "free"
  }
}

Pay-Per-Execution

{
  "pricing": {
    "model": "pay-per-execution",
    "basePrice": 0.01,
    "currency": "USDC"
  }
}

Subscription

{
  "pricing": {
    "model": "subscription",
    "monthlyPrice": 10.0,
    "currency": "USDC"
  }
}

Publishing Process

POST /api/sdk/v1/scripts/{scriptId}/publish
{
  "pricing": {
    "model": "pay-per-execution",
    "basePrice": 0.01,
    "currency": "USDC"
  },
  "category": "automation",
  "tags": ["telegram", "notifications"]
}

Troubleshooting

Timeout Errors

When scripts exceed the timeout limit:

  • Increase timeout configuration (up to 300 seconds)
  • Optimize slow operations (database queries, API calls)
  • Use caching to reduce redundant computations
  • Break long-running tasks into smaller chunks
  • Consider async/background processing for heavy workloads

Memory Errors

When scripts run out of memory:

  • Increase memory allocation (up to 3008 MB)
  • Process data in smaller batches
  • Remove unnecessary variables and large objects
  • Use streaming for large file processing
  • Monitor memory usage during development

Cost Limit Errors

When executions exceed cost limits:

  • Review resource usage (external API calls, LLM tokens)
  • Increase maxCostPerExecution if justified
  • Optimize expensive operations
  • Cache frequently accessed data
  • Set up cost alerts and monitoring

Event Subscription Not Firing

When event-triggered scripts don't execute:

  • Verify subscription is enabled
  • Check filter conditions match event structure
  • Test subscription with manual event trigger
  • Review execution history for errors
  • Ensure script is deployed (not draft)

Deployment Failures

When script deployment fails:

  • Check for syntax errors in code
  • Verify all required dependencies are installed
  • Test code locally before deployment
  • Review deployment logs for specific errors
  • Ensure code size is under 50 MB

Best Practices

Code Organization

// Good: Modular, testable structure
export async function handler(event, context) {
  const validated = validateInput(event);
  if (!validated.valid) {
    return { error: validated.error };
  }
  
  const result = await processEvent(validated.data);
  return { success: true, result };
}
 
function validateInput(event) {
  // Validation logic
}
 
async function processEvent(data) {
  // Processing logic
}

Error Handling

// Good: Comprehensive error handling
export async function handler(event, context) {
  try {
    // Validate input
    if (!event.data) {
      throw new Error('Missing required field: data');
    }
    
    // Process with timeout protection
    const result = await Promise.race([
      processData(event.data),
      timeoutAfter(25000) // 25s timeout
    ]);
    
    return { success: true, result };
  } catch (error) {
    console.error('Execution failed:', error);
    
    // Return structured error
    return {
      success: false,
      error: error.message,
      errorType: error.constructor.name,
      timestamp: new Date().toISOString()
    };
  }
}

Logging

// Good: Structured logging
export async function handler(event, context) {
  console.log('Execution started', {
    scriptId: context.scriptId,
    eventType: event.type,
    timestamp: new Date().toISOString()
  });
  
  const result = await processEvent(event);
  
  console.log('Execution completed', {
    duration: Date.now() - context.startTime,
    resultSize: JSON.stringify(result).length
  });
  
  return result;
}

Testing

// Good: Testable handler with separated logic
export async function handler(event, context) {
  return await processEvent(event, context);
}
 
export async function processEvent(event, context) {
  // Testable logic
  const data = transformData(event.data);
  return { success: true, data };
}
 
// Test file
const { processEvent } = require('./script');
 
test('processes event correctly', async () => {
  const event = { data: { value: 42 } };
  const result = await processEvent(event, {});
  expect(result.success).toBe(true);
});

Performance

  • Minimize cold starts: Keep initialization code outside the handler
  • Reuse connections: Create database/API clients outside handler
  • Use appropriate memory: Higher memory = more CPU
  • Batch operations: Group multiple API calls together
  • Cache results: Store frequently accessed data

See Also

On this page