Skip to main content
Version: 3.20.0 (stable)

Design Trade-offs

mimOE is designed to run on any device, from phones to servers, with a minimal footprint. To achieve this portability, the runtime makes deliberate trade-offs: a lightweight runtime instead of a full Node.js environment. Understanding these trade-offs helps you build mims that work reliably across every platform mimOE supports.

JavaScript Runtime

Not a Node.js Runtime

Key Difference

The mimOE JavaScript runtime is not Node.js. It is a lightweight ES5-based runtime built for portability across all supported platforms. Node.js built-in modules are not available.

The most common mistake developers make is trying to import Node.js modules:

// ❌ Node.js modules are NOT available
const fs = require('fs'); // Not available
const path = require('path'); // Not available
const http = require('http'); // Not available
const net = require('net'); // Not available
const crypto = require('crypto'); // Not available
const child_process = require('child_process'); // Not available

Instead, use the mimOE runtime APIs provided via the context object:

// ✅ Use mimOE runtime APIs
app.get('/data', (request, response) => {
// HTTP requests via context.http (with callbacks)
context.http.request({
url: 'https://api.example.com/data',
success: (result) => {
// Storage via context.storage (synchronous)
context.storage.setItem('key', result.data);
response.end(result.data);
},
error: (err) => {
response.statusCode = 500;
response.end(err.message);
}
});
});

For the complete list of available APIs, see the JavaScript mim Runtime API.

ES5 Runtime with Transpilation

The mimOE JavaScript runtime is ES5-compatible. However, you can write modern ES6+ JavaScript by using Webpack with Babel to transpile your code before deployment:

// You can write modern JavaScript
const add = (a, b) => a + b;
const message = `Hello ${name}`;
async function fetchData() { ... }

// Webpack + Babel transpiles to ES6 for deployment

See Toolchain Setup for configuration details.

What's Available vs. What's Not

AvailableNot Available
context.httpfetch, XMLHttpRequest
context.storagefs, localStorage
console.log (debugging)process, __dirname

Stateless Execution

mimOE uses a serverless execution model for efficiency and predictability.

No State Persists Between Requests

// ❌ WRONG - State is lost after each request
var requestCount = 0;

app.get('/count', (request, response) => {
requestCount++; // Always 1!
response.end(JSON.stringify({ count: requestCount }));
});
// ✅ CORRECT - Use context.storage
app.get('/count', (request, response) => {
var count = parseInt(context.storage.getItem('requestCount') || '0');
var newCount = count + 1;
context.storage.setItem('requestCount', String(newCount));
response.end(JSON.stringify({ count: newCount }));
});

Timers Within Execution Quota

setTimeout is available and runs within the request's execution quota. When the quota expires, all timers are terminated.

// ✅ Works within the execution quota
setTimeout(function() {
context.storage.setItem('delayed', 'true');
}, 1000);

// ❌ Not yet available (planned)
setInterval(function() {
// Use setTimeout in a loop as an alternative
}, 5000);

For long-running or recurring tasks, use external schedulers (cron jobs, cloud functions) to trigger mims via HTTP.

WASM Runtime

No WASI Support

mimOE's WebAssembly runtime does not support WASI (WebAssembly System Interface).

// ❌ WASI functions not available
use std::fs::File; // Won't work
use std::env; // Won't work

Alternative: Use mimOE's custom imported functions:

// ✅ Use mimOE imports
extern "C" {
fn storage_get(key_ptr: *const u8, key_len: usize) -> i32;
fn http_get(url_ptr: *const u8, url_len: usize) -> i32;
}

See WASM mims for more information (detailed API reference coming soon).

Networking

No Direct Socket Access

mims cannot create sockets or listen on ports:

// ❌ Not available
const net = require('net');
const server = net.createServer();

Alternative: Use context.http for outbound HTTP requests. Inbound requests are handled by the runtime.

Built-in API Gateway

mimOE provides a built-in API gateway that handles all web server concerns. Every mim receives HTTP requests automatically, so you only need to handle request events:

// No web server setup needed. Just handle requests.
app.get('/hello', (request, response) => {
response.end(JSON.stringify({ message: 'Hello from my mim!' }));
});

app.post('/data', (request, response) => {
var body = request.body;
context.storage.setItem('data', JSON.stringify(body));
response.end(JSON.stringify({ status: 'saved' }));
});

For outbound requests, use context.http which supports both HTTP and HTTPS:

context.http.request({
url: 'https://api.example.com/data',
success: (result) => {
response.end(result.data);
},
error: (err) => {
response.statusCode = 500;
response.end(err.message);
}
});

Streaming Support

Server-Sent Events (SSE) and chunked transfer encoding are supported. WebSocket support is planned for a future release.

// ✅ SSE and chunked transfer supported
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Transfer-Encoding', 'chunked');

// ❌ WebSockets not yet supported
const ws = new WebSocket('ws://example.com');

Storage

Key-Value Store Only

context.storage is a key-value store with tag support, not a relational database:

// ✅ Simple key-value operations (synchronous)
context.storage.setItem('user:123', JSON.stringify({ name: 'Alice' }));
var user = JSON.parse(context.storage.getItem('user:123'));

// ✅ Tagged storage for collections
context.storage.setItemWithTag('user:123', JSON.stringify(user), 'users');

// ✅ Paginated queries with filters
context.storage.getJsonItemsPaginated(0, 10, callback, {
tag: 'users',
filters: [{ jsonPath: '$.age', comparisonOperator: '>', value: '18' }]
});

// ❌ SQL queries not available
context.storage.query('SELECT * FROM users WHERE age > 18'); // Not available

Alternative: For complex relational queries, use an external database via context.http.

Cross-Platform Considerations

Mobile Platform Differences

On iOS and Android, mimOE runs embedded within an application:

  • Integrated within your app (not standalone)
  • Background execution follows OS guidelines
  • App sandbox restrictions apply

Workarounds and Best Practices

Use Polyfills

For missing features, use polyfills via Webpack:

// webpack.config.js
module.exports = {
resolve: {
fallback: {
"promise": require.resolve("promise-polyfill"),
"buffer": require.resolve("buffer/")
}
}
};

Optimize for Stateless

Design mims for stateless execution:

  • Use context.storage for any data that must persist
  • Keep request handlers pure functions when possible
  • Cache expensive computation results in storage
  • Validate all inputs (don't assume previous state)

Use Transactions for Consistency

Use lockExecute for atomic operations:

// ❌ Not atomic - could be inconsistent if interrupted
context.storage.setItem('balance:alice', String(aliceBalance - amount));
context.storage.setItem('balance:bob', String(bobBalance + amount));

// ✅ Atomic - all operations execute together
context.storage.lockExecute(function() {
context.storage.setItem('balance:alice', String(aliceBalance - amount));
context.storage.setItem('balance:bob', String(bobBalance + amount));
});

Summary

Trade-offWhyAlternative
Not Node.jsLightweight, portable runtimeUse context.* APIs
ES5 runtimeRuns on all platformsUse Webpack + Babel for ES6
StatelessEfficient serverless executioncontext.storage
No WASICross-platform WASM compatibilityCustom imports
No WebSockets (planned)SSE and chunked transfer supportedPolling or external service
KV storage onlyMinimal resource footprintExternal database via HTTP

Next Steps

Now that you understand the design trade-offs:

tip

These trade-offs are what make mimOE run anywhere, from phones to servers to embedded devices, with a minimal footprint.