# Resilient, Scalable Applications, Built Simply

Journey lets you define your business logic as a computation graph. It runs executions of your graph, with built-in persistence, fault tolerance, and horizontal scalability.

An Elixir package, Journey simply scales with your Elixir application. No additional infrastructure to deploy, no additional cloud service runtime dependencies to take on.

# Examples

Here are a couple of examples of building applications with Journey: a basic two-node Useless Machine, and a more functionality-rich Credit Card Application Service.

## Useless Machine

Note: this example is included in Journey's codebase (opens in a new window) .

A useless machine (opens in a new window) is a device whose only function is to turn itself off.

Show more

Here is a Journey graph implementing a useless machine with two nodes (:switch and :paw). The definition of :paw includes a function (&lol_no/1) that defines what :paw does when :switch changes:

defmodule UselessMachine do
  import Journey.Node

  def graph() do
    Journey.new_graph(
      "useless machine example graph",
      "v1.0.0",
      [
        input(:switch),
        mutate(:paw, [:switch], &lol_no/1, mutates: :switch)
      ]
    )
  end

  def lol_no(%{switch: switch}) do
    IO.puts("paw says: '#{switch}? lol no'")
    {:ok, "off"}
  end
end

Below is an example of using this useless machine.

The code creates an "execution" of the graph, and then flips its :switch to "on", and watches the :paw node wake up and flip the :switch back to "off" (some of IEX output omitted for brevity):

~/src/new_journey $ iex -S mix
iex(1)> graph = UselessMachine.graph()
iex(2)> execution = Journey.start_execution(graph)
iex(3)> Journey.get_value(execution, :switch)
{:error, :not_set}
iex(4)> Journey.get_value(execution, :paw)
{:error, :not_set}
iex(5)> Journey.set(execution, :switch, "on")
paw says: 'on? lol no'
iex(6)> Journey.get_value(execution, :paw)
{:ok, "updated :switch (at 1752361554)"}
iex(7)> Journey.get_value(execution, :switch)
{:ok, "off"}
iex(8)> Journey.set(execution, :switch, "on")
paw says: 'on? lol no'
iex(9)> Journey.get_value(execution, :paw)
{:ok, "updated :switch (at 1752361589)"}
iex(10)> Journey.get_value(execution, :switch)
{:ok, "off"}

We could keep flipping the switch on, and then watching paw turn it off until the end of time, or until the server crashes.

As long as you took a note of the ID of the execution, you can always load the execution when the application is back up, and continue where you left off, as if nothing happened.

Journey gives your application resiliency.

iex(11)> execution.id
"EXECLA7DTA19GX626M866MR3"
~/src/new_journey $ iex -S mix
iex(1)> _graph = UselessMachine.graph()
iex(2)> execution = Journey.load("EXECLA7DTA19GX626M866MR3")
iex(3)> Journey.set(execution, :switch, "on")
paw says: 'on? lol no'
iex(4)> Journey.get_value(execution, :paw)
{:ok, "updated :switch (at 1752435125)"}

## Credit Card Application Service

The Credit Card Application service is a more complex application, which includes multiple nodes holding data provided by the customer (name, ssn#), or computed by the graph itself (e.g. credit score) when the node's upstream data becomes available, or actions scheduled for later (e.g. sending a reminder to a pre-approved customer if they didn't request a credit card within a week), etc.

The essence of the application boils down to

1. the rules of the business captured in its Journey graph, and

2. the functions that perform various actions in self-computing nodes (e.g. send_preapproval_reminder() function, which sends the customer a reminder email).

This example (the journey graph, placeholder business logic, doctests) can be found in Journey's codebase (opens in a new window) .