Skip to content

System Overview

EvidentSource is designed as a cloud-native event sourcing platform that combines the reliability of a database with the flexibility of an application platform. This page provides an overview of the system architecture and key design decisions.

graph TB
subgraph "Clients"
A[JVM Client]
B[REST Client]
C[gRPC Client]
end
subgraph "API Layer"
D[REST API]
E[gRPC API]
F[Web UI]
end
subgraph "Core Server"
G[Command Handler]
H[Query Engine]
I[WebAssembly Runtime]
J[Index Manager]
end
subgraph "Storage Layer"
K[Storage Adapter Interface]
L[In-Memory]
M[DynamoDB+SNS]
N[DynamoDB+Kafka]
end
A --> E
B --> D
C --> E
D --> G
D --> H
E --> G
E --> H
F --> D
G --> K
H --> K
H --> I
I --> K
J --> K
K --> L
K --> M
K --> N

The API layer provides multiple interfaces for interacting with EvidentSource:

  • gRPC API: High-performance binary protocol for programmatic access
  • REST API: HTTP/JSON interface for web applications and simple integrations
  • Web UI: Browser-based interface for exploration and management

All APIs provide the same core functionality:

  • Database management (create, delete, list)
  • Event transactions (write batches with constraints)
  • Event queries (flexible filtering and temporal queries)
  • State View management and querying

Processes write operations:

  • Batch Validation: Ensures events meet CloudEvents specification
  • Constraint Checking: Validates optimistic concurrency constraints
  • Atomic Commits: All-or-nothing batch transactions
  • Revision Assignment: Assigns monotonic revision numbers
  • Metadata Capture: Records origin context (HTTP/gRPC/Kafka) for auditing

Handles read operations efficiently:

  • Index Navigation: Uses stream, subject, and type indexes
  • Temporal Queries: Supports bi-temporal querying
  • Event Selection: Complex AND/OR filtering logic
  • Streaming Results: Efficient iteration over large result sets

Executes user-defined components:

  • Wasmtime Integration: High-performance WebAssembly runtime
  • Component Model: Support for WASI preview2 components
  • State Views: Reduce functions for materialized views
  • State Changes: Command processors that emit events
  • Isolation: Each component runs in its own sandbox

Maintains queryable indexes:

  • Multi-Dimensional Indexing: By stream, subject, type, and time
  • Lazy Construction: Indexes built on first query
  • Incremental Updates: Efficient append-only updates
  • Memory Efficiency: Shared immutable data structures

EvidentSource uses a pluggable storage architecture:

trait StorageAdapter {
// Database operations
async fn create_database(&self, name: &str) -> Result<()>;
async fn delete_database(&self, name: &str) -> Result<()>;
// Event operations
async fn append_events(&self, db: &str, events: Vec<Event>) -> Result<Revision>;
async fn read_events(&self, db: &str, range: Range<Revision>) -> Result<Vec<Event>>;
// Index operations
async fn update_indexes(&self, db: &str, events: &[Event]) -> Result<()>;
async fn query_index(&self, db: &str, query: &Query) -> Result<Vec<Revision>>;
}

For development and testing:

  • All data stored in RAM
  • Fast performance for small datasets
  • No persistence between restarts
  • Perfect for unit tests and local development

For AWS production deployments:

  • DynamoDB Tables:
    • Events table: Stores all events
    • Indexes table: Stream, subject, type indexes
    • Databases table: Database metadata
  • SNS Topics: Real-time event notifications
  • S3 Integration: Large event storage (planned)
  • Auto-scaling: Handles varying workloads

Alternative streaming option:

  • Same DynamoDB storage as above
  • Kafka for event streaming instead of SNS
  • Better for high-throughput scenarios
  • Supports replay and consumer groups
  1. Client Request: Batch of events with constraints
  2. Validation: CloudEvents format and size limits
  3. Constraint Check: Verify optimistic concurrency
  4. Storage Write: Atomic append to event log
  5. Index Update: Update relevant indexes
  6. Notification: Publish to SNS/Kafka
  7. Response: Return new revision number
  1. Client Query: Event selection criteria
  2. Index Lookup: Find matching revisions
  3. Event Fetch: Retrieve events by revision
  4. State View: Optional materialization via WASM
  5. Response: Stream results to client
  • Stateless Servers: Any server can handle any request
  • Shared Storage: All state in DynamoDB/S3
  • Load Balancing: Standard ALB/NLB support
  • Auto-scaling Groups: Scale based on load
  • Index Chunking: Large indexes split into chunks
  • Lazy Loading: Indexes loaded on demand
  • Caching: Multi-level caching strategy
  • Batch Processing: Efficient batch operations
  • Zero-Copy: Minimize data copying
  • Event Size: 64KB per event
  • Batch Size: 25 events per batch (configurable)
  • Database Name: 63 characters, DNS-compliant
  • Query Results: Paginated for large datasets
  • API Keys: For programmatic access
  • IAM Integration: For AWS deployments
  • TLS/HTTPS: Encrypted transport
  • Database Isolation: Complete separation between databases
  • Encryption at Rest: Via DynamoDB/S3
  • Encryption in Transit: TLS 1.2+
  • Immutable Events: No modification after write
  • Audit Trail: Every change is recorded
  • Atomic Batches: All-or-nothing semantics
  • Idempotent Operations: Safe to retry
  • Consistency Guarantees: Strong consistency
  • Graceful Degradation: Partial availability
  • Point-in-Time Recovery: Via DynamoDB
  • Cross-Region Replication: DynamoDB Global Tables
  • Backup/Restore: Full database snapshots
  • Event Replay: Rebuild from event log
  • Event Rate: Events per second
  • Query Latency: Response time percentiles
  • Storage Usage: By database and index
  • Error Rates: By operation type
  • Structured Logs: JSON format
  • Correlation IDs: Request tracing
  • Error Details: Full error context
  • Performance Logs: Slow query logging
  • OpenTelemetry: Distributed tracing
  • Span Context: Through full request lifecycle
  • Custom Attributes: Business context
  • Integration: Works with Jaeger, Zipkin, etc.

Everything is an event:

  • State changes are events
  • Commands produce events
  • Views are derived from events
  • History is preserved in events

Data is append-only:

  • Events cannot be modified
  • Indexes are immutable structures
  • History is permanent
  • Corrections are new events

Keep it simple:

  • CloudEvents standard format
  • REST/gRPC standard protocols
  • WebAssembly standard runtime
  • SQL-like query language

User-defined behavior:

  • Custom State Views
  • Custom State Changes
  • Pluggable storage
  • Standard interfaces