<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ismael Celis</title>
    <link>https://ismaelcelis.com/</link>
    <description>Recent content on Ismael Celis</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 03 Dec 2025 09:10:00 +0000</lastBuildDate>
    <atom:link href="https://ismaelcelis.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>November 2025 talk on durable messaging and Ruby</title>
      <link>https://ismaelcelis.com/posts/2025-12-lrug-durable-messaging/</link>
      <pubDate>Wed, 03 Dec 2025 09:10:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/2025-12-lrug-durable-messaging/</guid>
      <description>&lt;p&gt;This is a presentation about durable messaging, Event Sourcing and Ruby that I gave at the &lt;a href=&#34;https://lrug.org/meetings/2025/november/&#34;&gt;London Ruby User Group&lt;/a&gt; this past November.&lt;/p&gt;&#xA;&lt;video controls width=&#34;100%&#34; style=&#34;margin-top: 2rem&#34;&gt;&#xA;  &lt;source src=&#34;https://assets.lrug.org/videos/2025/november/ismael-celis-durable-messaging-and-related-patterns-for-fun-and-profit-lrug-nov-2025.mp4&#34; type=&#34;video/mp4&#34; /&gt;&#xA;&lt;/video&gt;</description>
    </item>
    <item>
      <title>Unfinished business</title>
      <link>https://ismaelcelis.com/posts/2025-11-unfinished-business/</link>
      <pubDate>Tue, 04 Nov 2025 10:10:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/2025-11-unfinished-business/</guid>
      <description>&lt;p&gt;The conventional distinction between &amp;ldquo;foreground&amp;rdquo; request handling and &amp;ldquo;background&amp;rdquo; operations in web development is broken, misleading, and incomplete.&lt;/p&gt;&#xA;&lt;p&gt;There, I said it.&lt;/p&gt;&#xA;&lt;figure class=&#34;post-figure&#34;&gt;&#xA;  &lt;img src=&#34;https://ismaelcelis.com/images/2025/unfinished-business/conventional-flow.png&#34; alt=&#34;Conventional browser, controller, background job flow&#34; /&gt;&#xA;  &lt;figcaption&gt;Conventional browser, controller, background job flow&lt;/figcaption&gt;&#xA;&lt;/figure&gt;</description>
    </item>
    <item>
      <title>Baltic Ruby 2025 talk: an Event-Sourced programming model for Ruby</title>
      <link>https://ismaelcelis.com/posts/2025-09-baltic-ruby-event-sourcing-talk/</link>
      <pubDate>Tue, 02 Sep 2025 10:10:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/2025-09-baltic-ruby-event-sourcing-talk/</guid>
      <description>&lt;p&gt;Video of a presentation on Ruby and Event Sourcing I gave at &lt;a href=&#34;https://balticruby.org&#34;&gt;Baltic Ruby 2025&lt;/a&gt; back in June.&lt;/p&gt;&#xA;&lt;figure class=&#34;post-figure&#34;&gt;&#xA;  &lt;a href=&#34;https://www.youtube.com/watch?v=EgUwnzUJHMA&#34; title=&#34;Watch on YouTube&#34;&gt;&#xA;    &lt;img src=&#34;https://ismaelcelis.com/images/2025/baltic-ruby-2025.jpeg&#34; alt=&#34;Baltic Ruby 2025 talk: an Event-Sourced programming model for Ruby&#34; /&gt;&#xA;  &lt;/a&gt;&#xA;  &lt;figcaption&gt;Watch the talk on &lt;a href=&#34;https://www.youtube.com/watch?v=EgUwnzUJHMA&#34;&gt;YouTube&lt;/a&gt;&lt;/figcaption&gt;&#xA;&lt;/figure&gt;</description>
    </item>
    <item>
      <title>Said elsewhere (August 2025)</title>
      <link>https://ismaelcelis.com/posts/2025-08-said-elsewhere/</link>
      <pubDate>Fri, 29 Aug 2025 22:59:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/2025-08-said-elsewhere/</guid>
      <description>&lt;p&gt;Things I&amp;rsquo;ve said on &lt;a href=&#34;https://bsky.app/profile/ismaelcelis.com&#34;&gt;Bluesky&lt;/a&gt; in August 2025.&#xA;On Event Sourcing, Domain-Driven Design, Ruby, and software architecture.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Identity and behaviour</title>
      <link>https://ismaelcelis.com/posts/2025-07-identity-and-behaviour/</link>
      <pubDate>Thu, 10 Jul 2025 22:59:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/2025-07-identity-and-behaviour/</guid>
      <description>&lt;p&gt;In Object Oriented programming, identity and behaviour are often conflated. But it can be useful to think of them as different concepts.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Give it time</title>
      <link>https://ismaelcelis.com/posts/2025-04-give-it-time/</link>
      <pubDate>Mon, 21 Apr 2025 22:59:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/2025-04-give-it-time/</guid>
      <description>&lt;p&gt;Our experience of reality is based on the passage of time. Things begin and end, events happen one after the other. The world &lt;em&gt;changes&lt;/em&gt;.&#xA;And yet we model software as static object graphs frozen in time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Dead Code Podcast Notes</title>
      <link>https://ismaelcelis.com/posts/2025-01-dead-code-podcast-notes/</link>
      <pubDate>Tue, 14 Jan 2025 11:55:54 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/2025-01-dead-code-podcast-notes/</guid>
      <description>&lt;p&gt;I was recently invited to chat at the &lt;a href=&#34;https://shows.acast.com/dead-code/episodes/event-horizon-with-ismael-celis&#34;&gt;Dead Code podcast&lt;/a&gt; (thank you for the invite!), about Event Sourcing and Ruby. Here are some notes (and corrections!) from the conversation.&lt;/p&gt;</description>
    </item>
    <item>
      <title>What do commands do in Event Sourcing</title>
      <link>https://ismaelcelis.com/posts/what-do-commands-do-in-event-sourcing/</link>
      <pubDate>Sun, 22 Dec 2024 11:00:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/what-do-commands-do-in-event-sourcing/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been playing with and exploring &lt;a href=&#34;https://ismaelcelis.com/posts/event-sourcing-ruby-examples/&#34;&gt;Event Sourcing&lt;/a&gt; for a while now, but only recently realised that part of my thinking might have been muddled by unexamined assumptions about what commands are and what they do in the context of Event Sourcing.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Decide, Evolve, React pattern in Ruby</title>
      <link>https://ismaelcelis.com/posts/decide-evolve-react-pattern-in-ruby/</link>
      <pubDate>Mon, 16 Sep 2024 11:00:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/decide-evolve-react-pattern-in-ruby/</guid>
      <description>The Decide, Evolve, React pattern provides a unified mechanism for expressing, handling and reacting to state changes in a system.&#xA;It optionally provides a lossless audit trail of changes, and the seeds of a pub/sub sub-system, by tying together events to the state changes they cause.&#xA;It&amp;rsquo;s a generalisation of the Event Sourcing pattern, but it doesn&amp;rsquo;t require a log of events or a replay mechanism, and can be readily leveraged by traditional CRUD systems.</description>
    </item>
    <item>
      <title>Railway-Oriented Pipelines in Ruby pt. 5: Testing pipelines</title>
      <link>https://ismaelcelis.com/posts/railway-oriented-ruby-testing/</link>
      <pubDate>Wed, 20 Mar 2024 14:00:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/railway-oriented-ruby-testing/</guid>
      <description>In this series:&#xA;Part 1: Practical Railway-Oriented Pipelines in Ruby Part 2: User input, errors and metadata Part 3: Extending pipelines Part 4: Middleware Part 5: Testing pipelines Testing pipelines. Testing any complex workflow can be challenging. Composable pipelines can make it easier to use a &amp;ldquo;divide and conquer&amp;rdquo; approach to testing.&#xA;1. Unit test each step in isolation. Steps may or may not be complex, but their simple #call(Result) Result interface makes them easy to test.</description>
    </item>
    <item>
      <title>Railway-Oriented Pipelines in Ruby pt. 4: Middleware</title>
      <link>https://ismaelcelis.com/posts/railway-oriented-ruby-middleware/</link>
      <pubDate>Wed, 20 Mar 2024 13:00:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/railway-oriented-ruby-middleware/</guid>
      <description>In this series:&#xA;Part 1: Practical Railway-Oriented Pipelines in Ruby Part 2: User input, errors and metadata Part 3: Extending pipelines Part 4: Middleware Part 5: Testing pipelines In the previous article in this series I showed how to extend the basic pipeline with domain-specific steps and helpers.&#xA;Here I&amp;rsquo;ll show how to add middleware to the pipeline, to add tracing, logging, caching, and other cross-cutting concerns.&#xA;Middleware Middleware is a bit of code that wraps around each step in the pipeline, adding functionality to it.</description>
    </item>
    <item>
      <title>Railway-Oriented Pipelines in Ruby pt. 3: Extending pipelines</title>
      <link>https://ismaelcelis.com/posts/railway-oriented-ruby-extending-pipelines/</link>
      <pubDate>Wed, 20 Mar 2024 12:00:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/railway-oriented-ruby-extending-pipelines/</guid>
      <description>In this series:&#xA;Part 1: Practical Railway-Oriented Pipelines in Ruby Part 2: User input, errors and metadata Part 3: Extending pipelines Part 4: Middleware Part 5: Testing pipelines In the previous article in this series I showed how to pass extra metadata from one step to the next, including user input, errors and context data.&#xA;This article expands on the previous ones by showing how to extend the pipeline with domain-specific steps and helpers.</description>
    </item>
    <item>
      <title>Railway-Oriented Pipelines in Ruby pt.2: User input, errors and metadata</title>
      <link>https://ismaelcelis.com/posts/railway-oriented-ruby-result-metadata/</link>
      <pubDate>Wed, 20 Mar 2024 11:00:00 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/railway-oriented-ruby-result-metadata/</guid>
      <description>In this series:&#xA;Part 1: Practical Railway-Oriented Pipelines in Ruby Part 2: User input, errors and metadata Part 3: Extending pipelines Part 4: Middleware Part 5: Testing pipelines In the previous article I described a bare-bones implementation of Railway-oriented pipelines in Ruby. I showed how to build pipelines of steps that can be executed sequentially, with each step receiving the result of the previous one.&#xA;# An illustrative data processing pipeline DataImporter = Pipeline.</description>
    </item>
    <item>
      <title>Practical Railway-Oriented Pipelines in Ruby</title>
      <link>https://ismaelcelis.com/posts/practical-railway-oriented-pipelines-in-ruby/</link>
      <pubDate>Sun, 17 Mar 2024 12:19:16 +0000</pubDate>
      <guid>https://ismaelcelis.com/posts/practical-railway-oriented-pipelines-in-ruby/</guid>
      <description>In this series:&#xA;Part 1: Practical Railway-Oriented Pipelines in Ruby Part 2: User input, errors and metadata Part 3: Extending pipelines Part 4: Middleware Part 5: Testing pipelines Some years ago I explored patterns for building composable processing pipelines in Ruby, using a Railway-oriented paradigm.&#xA;In this series, I&amp;rsquo;ll describe a simplified implementation for practical use.&#xA;# An illustrative data processing pipeline DataImporter = Pipeline.new do |pl| pl.step ValidateUserInput pl.step ReadCSV pl.</description>
    </item>
    <item>
      <title>Event Sourcing with Ruby examples. The Command layer.</title>
      <link>https://ismaelcelis.com/posts/event-sourcing-ruby-command-layer/</link>
      <pubDate>Mon, 04 Jul 2022 10:00:00 +0100</pubDate>
      <guid>https://ismaelcelis.com/posts/event-sourcing-ruby-command-layer/</guid>
      <description>This is part of a series on Event Sourcing concepts, with Ruby examples. Read the previous part: Event Sourcing with Ruby examples. The Event Store interface.&#xA;The Command Layer is conceptually the place where business logic happens, user input is handled and decisions are made.&#xA;It’s not by any means unique to event-sourced apps, but present in all kinds of software in one way or the other.&#xA;In event-sourced apps it can take many forms, but the general flow is this:</description>
    </item>
    <item>
      <title>Event Sourcing with Ruby examples. The Event Store interface.</title>
      <link>https://ismaelcelis.com/posts/event-sourcing-ruby-event-store/</link>
      <pubDate>Tue, 28 Jun 2022 10:00:00 +0100</pubDate>
      <guid>https://ismaelcelis.com/posts/event-sourcing-ruby-event-store/</guid>
      <description>This is part of a series on Event Sourcing concepts, with Ruby examples. Read the first part: Event Sourcing from the ground up, with Ruby examples, part 1.&#xA;The Event Store interface is the canonical data store in event sourcing, and it’s in charge of persisting and retrieving events produced by your system.&#xA;#append_to_stream(stream_id String, events List&amp;lt;Event&amp;gt;) boolean #read_from_stream(stream_id String) List&amp;lt;Event&amp;gt; The stream_id is the identity of an entity in your domain.</description>
    </item>
    <item>
      <title>Event Sourcing from the ground up, with Ruby examples, part 1</title>
      <link>https://ismaelcelis.com/posts/event-sourcing-ruby-examples/</link>
      <pubDate>Mon, 27 Jun 2022 17:00:00 +0100</pubDate>
      <guid>https://ismaelcelis.com/posts/event-sourcing-ruby-examples/</guid>
      <description>In this series I&amp;rsquo;ll go over the basic concepts in Event Sourcing. The code examples are in Ruby, but the general principles should apply in any language.&#xA;What&amp;rsquo;s Event Sourcing The essential idea is that the state of objects in an app is tracked by a sequence of events describing discrete changes to those objects. For every state change, an event is produced and appended to a log in storage. Conversely, the current state of objects in the app is obtained by &amp;ldquo;replaying&amp;rdquo; all relevant events from the log and aggregating the described changes onto the object.</description>
    </item>
    <item>
      <title>Exploring Railway-Oriented programming in Ruby</title>
      <link>https://ismaelcelis.com/posts/composable-pipelines-in-ruby/</link>
      <pubDate>Thu, 14 Oct 2021 11:32:35 +0100</pubDate>
      <guid>https://ismaelcelis.com/posts/composable-pipelines-in-ruby/</guid>
      <description>An exploration of patterns for building composable data pipelines in Ruby, from the basics to the possibly YAGNI.&#xA;Function composition Ruby&amp;rsquo;s function composition allows you to neatly chain Procs together using the #&amp;gt;&amp;gt; operator.&#xA;DISCOUNT = 200 substract_discount = -&amp;gt;(amount) { amount - DISCOUNT } TAX_RATE = 0.19 add_tax = -&amp;gt;(amount) { amount * (1 + TAX_RATE) } calculate_total = substract_discount &amp;gt;&amp;gt; add_tax calculate_total.call(1000) # 952.0 #&amp;gt;&amp;gt; (and its inverse, #&amp;lt;&amp;lt;) are implemented in procs and method objects, so it&amp;rsquo;s possible to write class-based steps.</description>
    </item>
  </channel>
</rss>
