WASM Procedures: Migration Guide
WASM Procedures: Migration Guide
Documentation Home > User Guides > Features > Migration Guide
Overview
This guide provides practical examples and performance comparisons for migrating existing database procedures to HeliosDB WASM procedures from PL/pgSQL, JavaScript UDFs, and other procedural languages.
Related Sections:
- Quick Start - Getting started with WASM procedures
- Language SDKs - SDK documentation
- Performance - Performance benefits
Migration Guide
SQL Procedures to WASM
PL/pgSQL → Rust
Before (PL/pgSQL):
CREATE PROCEDURE calculate_bonus(emp_id INT)LANGUAGE plpgsqlAS $$DECLARE emp_salary DECIMAL(10,2); bonus DECIMAL(10,2);BEGIN SELECT salary INTO emp_salary FROM employees WHERE id = emp_id;
IF emp_salary > 100000 THEN bonus := emp_salary * 0.10; ELSE bonus := emp_salary * 0.05; END IF;
UPDATE employees SET bonus = bonus WHERE id = emp_id;END;$$;After (Rust/WASM):
use heliosdb_sdk::*;
#[procedure]pub fn calculate_bonus(emp_id: i64) -> Result<(), String> { let result = exec_sql(&format!( "SELECT salary FROM employees WHERE id = {}", emp_id ))?;
let emp_salary = result.get_f64(0, 0)?;
let bonus = if emp_salary > 100000.0 { emp_salary * 0.10 } else { emp_salary * 0.05 };
exec_sql(&format!( "UPDATE employees SET bonus = {} WHERE id = {}", bonus, emp_id ))?;
Ok(())}Benefits:
- 8x faster execution
- Type safety
- Better error handling
- Testable outside database
JavaScript UDFs → AssemblyScript
Before (JavaScript UDF):
function calculateTax(amount) { const taxRate = 0.08; return amount * taxRate;}After (AssemblyScript/WASM):
export function calculateTax(amount: f64): f64 { const taxRate: f64 = 0.08; return amount * taxRate;}Benefits:
- Type safety
- Faster execution
- Security isolation
Performance Comparison
Benchmark: 10,000 procedure calls
| Implementation | Total Time | Avg per Call | Memory |
|---|---|---|---|
| PL/pgSQL | 52,000ms | 5.2ms | 250 MB |
| PL/Python | 87,000ms | 8.7ms | 450 MB |
| WASM (Rust) | 6,200ms | 0.62ms | 45 MB |
| WASM (JS) | 11,000ms | 1.1ms | 62 MB |
| WASM (Python) | 14,500ms | 1.45ms | 89 MB |
| WASM (Go) | 8,100ms | 0.81ms | 53 MB |
Migration Strategies
1. Gradual Migration
Migrate procedures incrementally while keeping old procedures operational:
-- Keep existing PL/pgSQL procedureCREATE OR REPLACE PROCEDURE calculate_bonus_legacy(emp_id INT)LANGUAGE plpgsql AS $$ ... $$;
-- Create new WASM versionCREATE PROCEDURE calculate_bonus_wasm(emp_id BIGINT)LANGUAGE wasmAS '/opt/procedures/calculate_bonus.wasm';
-- Use feature flag to switchCREATE PROCEDURE calculate_bonus(emp_id INT)LANGUAGE sql AS $$ SELECT CASE WHEN current_setting('app.use_wasm', true) = 'true' THEN calculate_bonus_wasm(emp_id) ELSE calculate_bonus_legacy(emp_id) END;$$;2. A/B Testing
Test WASM procedures against existing implementations:
-- Route 10% of traffic to WASM versionCREATE PROCEDURE calculate_bonus(emp_id INT)LANGUAGE sql AS $$ SELECT CASE WHEN random() < 0.1 THEN calculate_bonus_wasm(emp_id) ELSE calculate_bonus_legacy(emp_id) END;$$;3. Shadow Mode
Run both versions and compare results:
CREATE PROCEDURE calculate_bonus_shadow(emp_id INT)LANGUAGE sql AS $$ WITH legacy_result AS ( SELECT calculate_bonus_legacy(emp_id) AS result ), wasm_result AS ( SELECT calculate_bonus_wasm(emp_id) AS result ) SELECT CASE WHEN l.result = w.result THEN l.result ELSE ( -- Log discrepancy SELECT log_mismatch('calculate_bonus', emp_id, l.result, w.result), l.result -- Return legacy result during shadow mode ) END FROM legacy_result l, wasm_result w;$$;Common Migration Patterns
Database Queries
PL/pgSQL:
SELECT column INTO variable FROM table WHERE condition;Rust WASM:
let result = exec_sql("SELECT column FROM table WHERE condition")?;let variable = result.get_string(0, 0)?;Loops
PL/pgSQL:
FOR record IN SELECT * FROM table LOOP -- Process recordEND LOOP;Rust WASM:
let result = exec_sql("SELECT * FROM table")?;for row in 0..result.row_count() { // Process row}Error Handling
PL/pgSQL:
BEGIN -- CodeEXCEPTION WHEN OTHERS THEN RAISE NOTICE 'Error: %', SQLERRM;END;Rust WASM:
match risky_operation() { Ok(value) => value, Err(e) => { log_error(&format!("Error: {}", e)); return Err(e); }}Migration Checklist
- Identify procedures to migrate (prioritize high-traffic, CPU-intensive)
- Choose target language (Rust for performance, Python for ML, etc.)
- Set up development environment with SDK
- Implement WASM version
- Write unit tests
- Deploy in shadow mode
- Compare results and performance
- Gradually roll out to production
- Monitor metrics and errors
- Retire legacy procedures
Next Steps
- API Reference - Complete API documentation
- Performance - Optimize migrated procedures
- Monitoring - Monitor migration success
Navigation: ← Advanced Topics | Index | API Reference →