Event sourcing + deterministic replay

The resilient execution platform

Workflow orchestration built on event sourcing. Start code-first, extend to visual workflows, run AI agents reliably.

OrderWorkflow.kt
class OrderWorkflow : WorkflowDefinition<OrderInput, OrderOutput>() {
    override val kind = "order-processing"
    override val name = "Order Processing"
    override val cancellable = true

    override suspend fun execute(ctx: WorkflowContext, input: OrderInput): OrderOutput {
        val payment = ctx.schedule<PaymentResult>("payment-task", input.paymentDetails)
        ctx.checkCancellation()

        val inventory = ctx.schedule<InventoryResult>("inventory-task", input.items)
        if (inventory.outOfStock) {
            ctx.run("refund") { refundPayment(payment.transactionId) }
            throw NonRetryableException("Inventory unavailable")
        }

        return OrderOutput(orderId = input.orderId, status = "completed")
    }
}

Core Capabilities

Everything you need to build reliable distributed workflows

Code-first Workflows

Write workflows in Kotlin with a simple WorkflowContext API. TypeScript and Python support planned. Event sourcing ensures deterministic replay.

Visual Builder

Drag-and-drop interface powered by your custom workers. Write handlers in any language, register via gRPC, compose visually.

AI Agent Execution

Resume agent loops at any point without losing state. Time-travel debugging lets you replay executions with different inputs.

Event Sourcing

Complete audit trail of all executions. Replay workflows from any point. Understand exactly what happened and why.

Built-in Resilience

Automatic retries, compensation logic, and failure handling. Focus on business logic, not infrastructure complexity.

Production-Grade

Multi-tenancy, quota enforcement, rate limiting, and data retention. gRPC communication protocol. Deploy on your infrastructure with full control.

Simple, Powerful API

The WorkflowContext API gives you everything you need for reliable execution

Side Effects & Tasks

// Side effects - cached on replay
val result = ctx.run("fetch-data") { 
    httpClient.get(url) 
}

// Long-running tasks - delegated
val payment = ctx.schedule<PaymentResponse>(
    "payment-task", 
    input
)

Deterministic Operations

// Deterministic - same value on replay
val id = ctx.randomUUID()
val now = ctx.currentTimeMillis()
val delay = ctx.random().nextInt(1000, 5000)

Durable State

// Persisted across restarts
ctx.set("status", "processing")
val status = ctx.get<String>("status")

Timers & Signals

// Durable timers and signals
ctx.sleep(Duration.ofHours(1))
val signal = ctx.promise<ApprovalResult>(
    "manager-approval"
)

What You Can Build

Flovyn handles the complexity of distributed workflows so you can focus on business logic

E-commerce

Order Processing with Automatic Compensation

Process orders across payment, inventory, and fulfillment with automatic compensation on failures. If delivery fails after payment, Flovyn automatically triggers refunds and inventory restoration.

Saga PatternCompensationDistributed Transactions
Billing

Subscription Billing with Payment Recovery

Handle failed payments with scheduled retries, notification escalation, and support team handoff. Ensures reminders aren't duplicated and maintains exact billing state for compliance.

Retry LogicState ManagementAudit Trail
AI Agents

Multi-step Research Agents

Agent loops that search web, analyze results, decide next steps, and compile reports. If the agent crashes mid-research, Flovyn resumes exactly where it left off without losing context.

AI ExecutionState PersistenceTime-travel Debug
Integration

Webhook Processing

Receive webhooks from payment providers, validate signatures, enrich with database context, update downstream systems. Guarantees exactly-once processing despite webhook retries.

Exactly-onceDeduplicationEvent Processing
Batch

Batch Processing with Fan-out/Fan-in

Process thousands of documents in parallel (OCR, ML inference, validation), aggregate results, handle partial failures by retrying specific items.

Parallel ExecutionPartial FailureAggregation
Enterprise

Multi-tenant Workflows

Build SaaS products with complete tenant isolation, quota enforcement, rate limiting, and team-based access control. Built-in multi-tenancy and RBAC.

Multi-tenancyRBACQuotas

Why Flovyn?

Stop reinventing distributed systems primitives. Focus on business logic.

Without Flovyn

  • Manual retry loops with exponential backoff
  • Database polling for timeouts
  • Custom state serialization
  • Distributed transaction coordination
  • Random UUID breaks replay

With Flovyn

  • ctx.schedule() with automatic retries
  • ctx.sleep(Duration.ofDays(7))
  • ctx.set('key', value) / ctx.get('key')
  • Saga pattern with ctx.run() compensation
  • ctx.randomUUID() deterministic on replay

How It Works

From code to production in three steps

1

Define Tasks

Create task handlers with the @TaskInfo annotation. Each task does one thing well with built-in timeout, retry, and progress reporting.

@Serializable
data class EmailInput(val to: String, val subject: String, val body: String)
@Serializable
data class EmailResult(val messageId: String, val status: String)

class SendEmailTask : TaskDefinition<EmailInput, EmailResult>() {
    override val kind = "send-email"
    override val name = "Send Email"
    override val description = "Sends email via SMTP"
    override val timeoutSeconds = 60

    override suspend fun execute(input: EmailInput, context: TaskContext): EmailResult {
        context.reportProgress(0.1, "Connecting to SMTP...")
        context.reportProgress(0.5, "Sending email...")
        val messageId = emailService.send(input)
        context.reportProgress(1.0, "Email sent")
        return EmailResult(messageId, "sent")
    }
}
2

Compose Workflows

Build workflows using the WorkflowContext API. Orchestrate tasks, handle failures, add compensation logic - all with full type safety.

@Serializable
data class UserInput(val email: String, val name: String)
@Serializable
data class OnboardingResult(val userId: String, val status: String)

class OnboardingWorkflow : WorkflowDefinition<UserInput, OnboardingResult>() {
    override val kind = "user-onboarding"
    override val name = "User Onboarding"
    override val description = "Onboards new users with welcome email and account setup"

    override suspend fun execute(ctx: WorkflowContext, input: UserInput): OnboardingResult {
        val user = ctx.run("create-user") { userService.create(input) }

        // Run email and account setup in parallel
        val emailTask = ctx.scheduleAsync<EmailResult>("send-email", EmailInput(input.email, "Welcome!", "..."))
        val setupTask = ctx.scheduleAsync<SetupResult>("setup-account", SetupInput(user.id))
        awaitAll(emailTask, setupTask)

        return OnboardingResult(user.id, "completed")
    }
}
3

Register and Start

Register your workflows and tasks with the Flovyn client using gRPC. They automatically appear in the visual builder and can be started via API or UI.

fun main() {
    val client = FlovynClient.builder()
        .serverAddress("localhost", 9090)
        .tenantId(myTenantId)
        .taskQueue("onboarding-workers")
        .registerWorkflow(OnboardingWorkflow())
        .registerTask(SendEmailTask())
        .registerTask(SetupAccountTask())
        .build()

    client.start() // Blocks and polls for work
}
AI Agent Execution

Run AI Agents Reliably

Agent loops that survive crashes and resume exactly where they left off

Resume from Any Point

Agent crashes mid-research? No problem. Flovyn resumes exactly where it stopped without losing context or duplicating work.

Time-Travel Debugging

Replay agent executions with different inputs or models. See exactly what decisions the agent made at each step.

ResearchAgent.kt
@Workflow(name = "research-agent")
class ResearchAgent : 
    TypedWorkflowDefinition<Query, Report> {
    
    override suspend fun execute(
        ctx: WorkflowContext, 
        input: Query
    ): Report {
        val results = mutableListOf<SearchResult>()

        while (results.size < 10) {
            val search = ctx.schedule<SearchResult>(
                "web-search", 
                input.query
            )
            results.add(search)

            val decision = ctx.schedule<AgentDecision>(
                "llm-decide", 
                results
            )
            if (decision.complete) break

            // Resume point on crash
            ctx.checkCancellation()
        }

        return ctx.schedule("compile-report", results)
    }
}

Running in Production

Built-in operational features for production workloads

Minimal Deployment

PostgreSQL + single Flovyn server. Start simple, scale as requirements grow.

Data Retention

Automatic retention with configurable policies. Optional S3-compatible archival for long-term storage.

Multi-tenancy

Built-in tenant isolation with quota enforcement and rate limiting. Perfect for SaaS products.

Self-hosted First

Run on your infrastructure with full control. No vendor lock-in, deploy anywhere.

Ready to Scale?

Add Redis for advanced features when needed. Start simple, grow as you go.

PostgreSQL
Flovyn Server
Redis (optional)

Build resilient workflows today

Start with code, extend to visual workflows, run AI agents reliably in production.

Built with v0