Skip to main content
This guide will walk you through creating your first Infinitic workflow. You’ll learn how to define services, orchestrate them with workflows, and run everything locally.

What You’ll Build

You’ll create a simple notification workflow that:
  • Sends an email notification
  • Waits for confirmation
  • Logs the result
This demonstrates Infinitic’s core capabilities: service execution, workflow orchestration, and state management.
1

Add Infinitic Dependencies

Add the Infinitic dependencies to your project:
dependencies {
    implementation("io.infinitic:infinitic-worker:0.18.2")
    implementation("io.infinitic:infinitic-client:0.18.2")
    implementation("io.infinitic:infinitic-transport-pulsar:0.18.2")
    implementation("io.infinitic:infinitic-storage:0.18.2")
}
2

Define Your Service

Create a service interface and implementation. Services contain the actual business logic.
NotificationService.kt
interface NotificationService {
    fun sendEmail(email: String, message: String): String
}

class NotificationServiceImpl : NotificationService {
    override fun sendEmail(email: String, message: String): String {
        // Simulate sending email
        println("Sending email to $email: $message")
        Thread.sleep(100)
        return "Email sent successfully to $email"
    }
}
Services are where you implement your actual business logic - API calls, database operations, external service integrations, etc. Infinitic handles execution, retries, and error handling.
3

Create a Workflow

Define a workflow interface and implementation. Workflows orchestrate services and define your business process.
NotificationWorkflow.kt
import io.infinitic.workflows.Workflow

interface NotificationWorkflow {
    fun process(email: String, message: String): String
}

class NotificationWorkflowImpl : Workflow(), NotificationWorkflow {
    // Create a stub for the service
    private val notificationService = newService(NotificationService::class.java)
    
    override fun process(email: String, message: String): String {
        // Execute the service
        val result = notificationService.sendEmail(email, message)
        
        // Return the result
        return result
    }
}
Workflows define the orchestration logic. They are deterministic and can be replayed, which means they shouldn’t contain any non-deterministic operations like Random() or direct API calls. Use services for those operations instead.
4

Configure Infinitic

Create a configuration file for your worker and client. This example uses in-memory transport for quick local development.
infinitic.yml
# Storage configuration (in-memory for development)
storage:
  inMemory:

# Transport configuration (Pulsar)
transport:
  pulsar:
    brokerServiceUrl: pulsar://localhost:6650
    webServiceUrl: http://localhost:8080
    tenant: infinitic
    namespace: dev

# Service configuration
services:
  - name: NotificationService
    executor:
      class: com.example.NotificationServiceImpl
      concurrency: 10

# Workflow configuration  
workflows:
  - name: NotificationWorkflow
    executor:
      class: com.example.NotificationWorkflowImpl
      concurrency: 10
For production use, replace in-memory storage with Redis, PostgreSQL, or MySQL. See the Installation guide for details.
5

Start a Worker

Workers execute your services and workflows. Create a worker application:
Worker.kt
import io.infinitic.workers.InfiniticWorker

fun main() {
    // Create worker from configuration file
    val worker = InfiniticWorker.fromYamlFile("infinitic.yml")
    
    // Start the worker (blocks until shutdown)
    worker.start()
}
Run your worker:
# Make sure Pulsar is running first
docker run -d -p 6650:6650 -p 8080:8080 apachepulsar/pulsar:latest bin/pulsar standalone

# Run your worker
./gradlew run
Workers are long-running processes that consume messages from Pulsar, execute tasks, and produce responses. You can run multiple workers for horizontal scaling.
6

Execute Your Workflow

Create a client to start workflows:
Client.kt
import io.infinitic.clients.InfiniticClient

fun main() {
    // Create client from configuration
    val client = InfiniticClient.fromYamlFile("infinitic.yml")
    
    // Create a workflow stub
    val workflow = client.newWorkflow(NotificationWorkflow::class.java)
    
    // Start the workflow and wait for result
    val result = workflow.process(
        email = "[email protected]",
        message = "Hello from Infinitic!"
    )
    
    println("Result: $result")
    
    // Close the client
    client.close()
}
Run your client:
./gradlew run --args="client"

What’s Happening?

When you execute the workflow:
  1. The client sends a message to start the workflow
  2. A workflow worker picks up the message and begins executing NotificationWorkflowImpl.process()
  3. When the workflow calls notificationService.sendEmail(), it dispatches a service task
  4. A service worker executes NotificationServiceImpl.sendEmail()
  5. The result flows back to the workflow, which completes and returns to the client
All state is persisted automatically, so workflows survive crashes and can run for days, weeks, or months.

Next Steps

Learn Core Concepts

Understand workflows, services, and how Infinitic works

Production Setup

Set up Infinitic with production-ready storage and transport

Advanced Features

Explore retries, timeouts, versioning, and more

Examples

Browse real-world examples and patterns

Build docs developers (and LLMs) love