Entry Points with Runtime
The most common way to run an Effect program is usingNodeRuntime.runMain or BunRuntime.runMain at your application entry point.
NodeRuntime.runMain
NodeRuntime.runMain is designed for Node.js applications. It automatically installs signal handlers (SIGINT/SIGTERM) for graceful shutdown and interrupts running fibers when the process receives a termination signal.
BunRuntime.runMain
Bun applications useBunRuntime.runMain, which has the same API shape as NodeRuntime.runMain:
Layer.launch for Long-Running Applications
When your entire application is composed of layers (HTTP servers, background workers, database connections), useLayer.launch to convert the layer into a long-running Effect program.
- Your app is entirely composed of layers
- You need multiple long-running services (HTTP server + workers)
- All services share common dependencies
ManagedRuntime for Framework Integration
ManagedRuntime bridges Effect programs with non-Effect code. Create one runtime from your application layer, then use it anywhere you need imperative execution—web handlers, framework hooks, worker queues, or legacy callback APIs.
Cleanup on Shutdown
When usingManagedRuntime, ensure you dispose of it on shutdown to clean up resources:
Runtime Execution Methods
ManagedRuntime provides multiple execution methods:
runtime.runPromise()- Returns a Promise (for async contexts)runtime.runSync()- Synchronous execution (for synchronous edges)runtime.runCallback()- Callback-based execution (for legacy APIs)runtime.runFork()- Returns a Fiber for manual control
Choosing the Right Approach
NodeRuntime.runMain / BunRuntime.runMain
NodeRuntime.runMain / BunRuntime.runMain
Use when:
- Building a standalone Effect application
- You control the entire process lifecycle
- You need graceful shutdown handling
Layer.launch
Layer.launch
Use when:
- Your app is entirely composed of layers
- Running multiple long-lived services
- All components share dependencies
ManagedRuntime
ManagedRuntime
Use when:
- Integrating Effect into existing frameworks
- Bridging Effect with non-Effect code
- Need imperative execution in callbacks/handlers
Best Practices
Single Runtime
Create one
ManagedRuntime per application and reuse it across handlers. Don’t create new runtimes per request.Memo Map
Always provide a shared
memoMap to ManagedRuntime.make for proper memoization across the app.Error Handling
Disable
disableErrorReporting if you have centralized error handling. Otherwise, errors are logged automatically.Resource Cleanup
Always call
runtime.dispose() on shutdown when using ManagedRuntime to properly clean up resources.Next Steps
Testing
Learn how to test Effect programs with @effect/vitest
Observability
Add logging, tracing, and metrics to your applications
