Designing Systems for the AI Coding Revolution: Achieving Regret-Free Architecture with Event Sourcing and the Actor Model

ยท

8 min read

Designing Systems for the AI Coding Revolution: Achieving Regret-Free Architecture with Event Sourcing and the Actor Model
๐Ÿ’ก
This article was created by first drafting with Cline + Claude 3.5 Sonnet based on my ideas, and then using Cline to iteratively refine and edit specific sections. Unlike pasting the entire text on the web for editing, this approach allowed me to adjust the content like writing code, section by section. While it took considerable time, I believe it resulted in an excellent article. Although the actual writing was done by LLMs, the content thoroughly reflects my own thoughts and feelings down to the details.

Introduction

In system development, "regrets" emerge from two distinct aspects. The first concerns data state changes: whether written by humans or generated by AI, incorrect programs can modify data in unintended ways, making recovery and correction difficult when using traditional approaches. The second relates to architectural choices: from hitting scalability limits with overly simple implementations to inefficient operations due to overengineering, architectural decisions have long-lasting implications.

In an era where AI-generated code is becoming the norm, these challenges become even more critical. While AI can generate code at unprecedented speeds, it introduces new risks of unintended changes, and systems must remain flexible enough to accommodate rapid business growth.

This article explores how combining Event Sourcing and the Actor Model creates a truly "regret-free" architecture that addresses both aspects:

  • Event Sourcing:

    • Complete preservation of change history
    • Tracking and recovery of unintended changes
    • Transparent management of both AI and human code changes
  • Actor Model:

    • Minimal initial investment (enabled by the framework)
    • Linear scaling with demand
    • Growth without architectural overhaul

The Challenges of AI Programming

The Debugging Imperative

AI-generated code presents unique challenges compared to human-written code:

  • Lightning-fast code generation
  • Ability to produce large volumes of code quickly
  • Less transparent decision-making process

These characteristics make it essential to maintain detailed records of system changes and their context.

Designing for Zero Regrets

Traditional state-based approaches have a significant drawback: once data is modified or deleted, tracking or reverting those changes becomes challenging. This is particularly problematic when dealing with unexpected modifications from AI-generated code.

By adopting Event Sourcing, we can create a truly regret-free system design:

  • Every data change is preserved as an immutable event
  • All modifications, including those from AI-generated code, are fully traceable
  • System state can be accurately reconstructed at any point in time
  • Changes that escaped human review can be discovered, fixed, or rolled back later

This approach provides crucial safety nets for rapid AI-assisted development:

  • Maintain development speed without sacrificing data traceability
  • Completely visualize and minimize the impact of AI-driven changes
  • Enable confident human oversight with the ability to review and correct at any time

The Value of Event Sourcing

Event Sourcing brings significant value to systems through three aspects: core functions, context preservation, and unexpected analytical insights. Let's explore each of these aspects in detail.

Core Functions - Three Pillars of System Reliability

Event Sourcing provides three essential capabilities that support system reliability and resilience:

  1. Complete Change History

    • All changes permanently recorded as events
    • No data deletion or overwriting
    • Accurate state reconstruction at any point in time
  2. Audit and Tracking

    • Track all operations, including AI-generated changes
    • Automatic generation of complete audit trails
    • Clear recording of change intentions and outcomes
  3. Advanced Recovery

    • State restoration when data inconsistencies are found
    • Post-review correction of changes that escaped human review
    • Enhanced overall system reliability

Context Preservation

Event Sourcing naturally preserves essential information:

  • Change intentions and reasoning
  • Environmental context
  • Business rules in effect
  • User and system states

Discovering Unexpected Analytical Value

One of the key advantages of Event Sourcing is that information not considered important during event recording can later become valuable analytical assets.

Consider a shopping cart in an e-commerce system:

  • Traditional Approach:

    • Only stores current cart state
    • Previous states are overwritten with additions/removals
    • User hesitation and interest patterns are lost
  • Event Sourcing:

    • All cart additions and removals are preserved as events
    • Can identify products users "hesitated" about
    • Enables rich recommendation features using historical data

This characteristic enables retrospective analysis and feature additions such as:

  • Identifying frequently considered but ultimately unpurchased items
  • Analyzing patterns in user interest shifts
  • Developing more accurate recommendation engines

While traditional logging or history features only capture data after implementation, Event Sourcing allows complete behavioral analysis reaching back to the system's beginning.

The Actor Model Advantage

The Actor Model complements Event Sourcing by providing scalability and reliability in distributed environments. Here's how it addresses the key challenges of modern system development.

Achieving Linear Scalability - From Single Server to Global Scale

The Actor Model enables natural system growth through gradual scaling, without requiring fundamental architectural changes:

  1. Initial Phase:

    • Start with minimal resources
    • Efficient operation on a single server
    • High return on investment
  2. Growth Phase:

    • Linear performance improvement with server additions
    • Selective scaling of specific components
    • Optimal balance between infrastructure costs and performance
  3. Large-Scale Systems:

    • Linear scaling up to hundreds of servers
    • No fundamental architectural changes needed
    • Flexible expansion at the component level

This characteristic allows natural expansion aligned with business growth, avoiding both the "scalability wall" and excessive initial infrastructure investments.

Synergy with Event Sourcing

The combination of Actor Model and Event Sourcing delivers powerful benefits:

  • Parallel event processing for high throughput
  • Natural state consistency through independent actors
  • Manageable system complexity
  • Isolated impact of AI-generated code changes
  • Scalable event stream processing

Practical Implementation: Sekiban.Pure.Orleans

Key Features

Our solution, Sekiban.Pure.Orleans, is a next-generation architectural solution that combines Event Sourcing with the Actor Model.

github.com/J-Tech-Japan/Sekiban

Initially developed as Sekiban.Core, our solution started as a single-server implementation that served many projects successfully. However, as we encountered challenges with data consistency during scale-out scenarios, we turned to the Actor Model as a solution. By incorporating Microsoft Orleans, we've achieved scalable operations while maintaining high data consistency in distributed environments.

Key features:

  • Modern C# syntax support
  • Distributed processing with Microsoft Orleans virtual actor model
  • Streamlined Event Sourcing implementation
  • Cost-effective operations
  • Rapid project bootstrapping with ready-to-use templates

Released in early 2024 as a preview version, it offers:

  • Reliable data consistency in distributed environments
  • Scale-out reliability
  • Simple developer experience

Getting started is incredibly simple. After setting up your C# environment, just run these two commands:

nuget.org/packages/OrleansSekiban.Template

dotnet new install OrleansSekiban.Template
dotnet new sekiban-orleans -n MySampleCode

This immediately provides you with a complete sample project that includes commands, events, and aggregates. The sample project is built with .NET Aspire and, after setting the Postgres password, launches a full local development environment including:

  • Actor cluster storage
  • State persistence storage
  • Event store
  • API Service
  • Blazor frontend project

Cost Efficiency

Example of a cost-effective initial setup:

You can get started for under $100/month by combining these Azure services:

  • Azure App Service B1 (1.75GB memory, 1 core)
  • Cosmos DB Serverless (for actor state and event store)
  • Azure Table Storage (for projection data)
  • Azure Blob Storage (for large data storage)

This configuration provides:

  • Scalability: Flexible expansion as needed
  • Operating costs: Usage-based billing with serverless options
  • Initial investment: Start with minimal resources

As your business grows, you can scale up individual components based on specific needs.

Implementation Example

The sample project includes practical implementations demonstrating the key concepts:

Aggregate Root

// Weather forecast aggregate root
public record WeatherForecast(
    string? Summary,
    int TemperatureC,
    DateTime Date) : IAggregatePayload<WeatherForecast>
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

    public static WeatherForecast Create(WeatherForecastInputted ev) =>
        new(ev.Summary, ev.TemperatureC, ev.Date);
}

Event Definition

// Weather forecast input event
public record WeatherForecastInputted(
    string Summary,
    int TemperatureC,
    DateTime Date) : IEventPayload;

Commands and Handlers

namespace MySampleCode.Domain;

// Command and handler defined in a single file
public record InputWeatherForecastCommand(string Summary, int TemperatureC, DateTime Date) : ICommand<WeatherForecast>
{
    public PartitionKeys SpecifyPartitionKeys(InputWeatherForecastCommand command) => 
        PartitionKeys.Generate<WeatherForecastProjector>();

    public ResultBox<EventOrNone> Handle(InputWeatherForecastCommand command, ICommandContext<IAggregatePayload> context)
        => EventOrNone.Event(new WeatherForecastInputted(command.Location, command.Date,command.TemperatureC, command.Summary));    
}

Projector (Read Model)

// Weather forecast projector
public class WeatherForecastProjector :
    IProjector<WeatherForecastProjector, WeatherForecastProjection>
{
    public required string Summary { get; init; }
    public required int TemperatureC { get; init; }
    public required DateTime Date { get; init; }
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

    // Update projection from event
    public static WeatherForecastProjector OnEvent(WeatherForecastInputted ev) =>
        new()
        {
            Summary = ev.Summary,
            TemperatureC = ev.TemperatureC,
            Date = ev.Date
        };
}

Queries

// Weather forecast query definition
public record GetWeatherForecastsQuery() : IQuery<List<WeatherForecastProjector>>;

// Query handler
public class GetWeatherForecastsQueryHandler :
    IQueryHandler<GetWeatherForecastsQuery, List<WeatherForecastProjector>>
{
    private readonly IProjectionRepository _repository;

    public GetWeatherForecastsQueryHandler(IProjectionRepository repository) =>
        _repository = repository;

    public async Task<List<WeatherForecastProjector>> Handle(
        GetWeatherForecastsQuery query,
        CancellationToken cancellationToken = default) =>
        await _repository.Lists<WeatherForecastProjector>();
}

This sample code demonstrates the key concepts of Event Sourcing and Actor Model:

  • State management through aggregate roots
  • Change tracking through events
  • Operations through commands and handlers
  • Read model through projectors
  • Data retrieval through queries

Conclusion: Achieving Regret-Free Architecture

The combination of Event Sourcing and Actor Model creates an ideal architecture for the AI programming era:

  1. Complete Safety and Resilience

    • Full visibility into AI-generated code impacts
    • Permanent preservation of all changes
    • Precise state restoration when needed
  2. Speed with Confidence

    • Maximized AI development capabilities
    • Early problem detection and resolution
    • Optimal human-AI collaboration
  3. Future-Proof Scalability

    • Natural growth with business needs
    • Superior parallel processing performance
    • Sustainable operational costs

Sekiban.Pure.Orleans makes these benefits of regret-free architecture accessible and affordable. It's particularly valuable for startups and small-to-medium businesses looking toward future growth. By adopting Event Sourcing and the Actor Model, teams can build innovative systems where humans and AI collaborate safely, without fear of irreversible changes.

ย