FAQ
Frequently asked questions about EVOID.
General
What is IOP?
Intent-Oriented Programming is a paradigm where data declares what it needs. The runtime handles how. Instead of writing “how to save a user,” you declare “this is critical data” and the runtime adds encryption, audit logging, and replication automatically.
When should I use EVOID?
Use EVOID when:
- Multiple services need to communicate
- Different data needs different infrastructure (payments need PostgreSQL, sessions need Redis)
- You want pipeline-based extensibility
- You need typed, validated processing chains
When should I NOT use EVOID?
EVOID is overkill for:
- Simple single-file scripts
- Tiny APIs with < 5 endpoints
- Projects where you don’t need pipeline extensibility
Is EVOID production-ready?
EVOID is in beta (v0.6.x). The core is stable, minimal dependencies, all tests passing. APIs may change before v1.0. Pin your version in production.
Technical
How does EVOID differ from middleware?
Traditional middleware wraps the entire request/response. EVOID processors run as part of a pipeline, with access to shared state (ctx.state). Processors are composable, replaceable, and can be injected at any point.
Can I use EVOID with FastAPI?
Yes. EVOID complements FastAPI. Use FastAPI for HTTP endpoints and EVOID for internal service communication, validation pipelines, and inter-service messaging.
What’s the performance overhead?
EVOID pipeline execution has near-zero overhead. The fast path (no inspection, no timeout) runs at ~10K ops/s on a 5-processor pipeline. Inspection and timeout add minimal cost.
How do I switch from SQLite to PostgreSQL?
Change evoid.toml and run evo sync:
[engines]
storage = "sqlalchemy"
evo sync
Zero code changes to your business logic.
How do I add authentication?
Use the built-in auth_checker processor with the simple auth engine:
from evoid.processors import auth_checker
from evoid.core.extend import before
before("GET:/users/{id}", "auth_checker")
Or create a custom processor (no plugin needed):
from evoid.core import Context, register_processor
async def check_auth(ctx: Context) -> dict:
token = ctx.intent.metadata.get("headers", {}).get("authorization")
if not token:
raise ValueError("Unauthorized")
ctx.state["user"] = verify_token(token)
return {"authenticated": True}
register_processor("check_auth", check_auth)
How do I handle errors?
Raise exceptions in processors. The pipeline stops and returns a failed Result:
result = await execute(intent)
if not result.success:
print(f"Error: {result.error}")
print(f"Failed after: {result.processors}")
For non-critical errors, append to ctx.errors:
ctx.errors.append(ValidationError("optional check failed"))
# Pipeline continues
How do I test my processors?
import asyncio
from evoid.core import Context, Intent, Level, register_processor
async def my_processor(ctx: Context) -> dict:
return {"valid": True}
async def test_my_processor():
intent = Intent(name="test", level=Level.STANDARD)
ctx = Context(intent=intent, state={"data": "hello"})
result = await my_processor(ctx)
assert result["valid"] is True
asyncio.run(test_my_processor())
CLI
How do I create a project?
evo init my-api
cd my-api
How do I add a service?
evo service new api
How do I run my service?
evo service run api
How do I sync dependencies?
evo sync
This reads evoid.toml and installs required packages.
Related
- Quick Start — Get started in 5 minutes
- What is IOP? — Understanding the paradigm
- Troubleshooting — Common errors and fixes
- Configuration — TOML config reference