Skip to main content
Building 
Reactive Systems 
with Akka 
Jonas Bonér 
Typesafe 
CTO & co-founder 
Twitter: @jboner
The rules of the game 
have changed
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks Fast networks
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks Fast networks 
Few concurrent users
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks Fast networks 
Few concurrent users Lots of concurrent users
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks Fast networks 
Few concurrent users Lots of concurrent users 
Small data sets
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks Fast networks 
Few concurrent users Lots of concurrent users 
Small data sets Large data sets
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks Fast networks 
Few concurrent users Lots of concurrent users 
Small data sets Large data sets 
Latency in seconds
3 
Apps in the 60s-90s 
were written for 
Apps today 
are written for 
Single machines Clusters of machines 
Single core processors Multicore processors 
Expensive RAM Cheap RAM 
Expensive disk Cheap disk 
Slow networks Fast networks 
Few concurrent users Lots of concurrent users 
Small data sets Large data sets 
Latency in seconds Latency in milliseconds
Cost Gravity is at Work 
X
Cost Gravity is at Work 
X
Reactive applications share four traits 
Reactive 
Applications 
5
Reactive applications enrich the user 
experience with low latency response.
Responsive 
• Real-time, engaging, rich and collaborative 
• Create an open and ongoing dialog with users 
• More efficient workflow; inspires a feeling of connectedness 
• Fully Reactive enabling push instead of pull 
7 
“The move to these technologies is already paying off. 
Response times are down for processor intensive code–such as image 
and PDF generation–by around 75%.” 
Brian Pugh, VP of Engineering, Lucid Software
Reactive applications react to 
changes in the world around them.
Message-Driven 
• Loosely coupled architecture, easier to extend, maintain, evolve 
• Asynchronous and non-blocking 
• Concurrent by design, immutable state 
• Lower latency and higher throughput 
9 
“Clearly, the goal is to do these operations concurrently and 
non-blocking, so that entire blocks of seats or sections are not locked. 
We’re able to find and allocate seats under load in less than 20ms 
without trying very hard to achieve it.” 
Andrew Headrick, Platform Architect, Ticketfly
Introducing the Actor Model
11 
The Actor Model
11 
The Actor Model 
A computational model that embodies:
11 
The Actor Model 
A computational model that embodies: 
✓ Processing
11 
The Actor Model 
A computational model that embodies: 
✓ Processing 
✓ Storage
11 
The Actor Model 
A computational model that embodies: 
✓ Processing 
✓ Storage 
✓ Communication
A computational model that embodies: 
✓ Processing 
✓ Storage 
✓ Communication 
Supports 3 axioms—when an Actor receives a message it can: 
11 
The Actor Model
A computational model that embodies: 
✓ Processing 
✓ Storage 
✓ Communication 
Supports 3 axioms—when an Actor receives a message it can: 
1. Create new Actors 
11 
The Actor Model
A computational model that embodies: 
✓ Processing 
✓ Storage 
✓ Communication 
Supports 3 axioms—when an Actor receives a message it can: 
1. Create new Actors 
2. Send messages to Actors it knows 
11 
The Actor Model
A computational model that embodies: 
✓ Processing 
✓ Storage 
✓ Communication 
Supports 3 axioms—when an Actor receives a message it can: 
1. Create new Actors 
2. Send messages to Actors it knows 
3. Designate how it should handle the next message it receives 
11 
The Actor Model
The essence of an actor 
from Akka’s perspective 
0. DEFINE 
1. CREATE 
2. SEND 
3. BECOME 
4. SUPERVISE 
12
public class Greeting implements Serializable { 
public final String who; 
public Greeting(String who) { this.who = who; } 
} 
! 
public class Greeter extends AbstractActor {{ 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchAny(unknown -> { 
println(“Unknown message " + unknown); 
}).build()); 
}} 
0. DEFINE 
X
public class Greeting implements Serializable { 
public final String who; 
public Greeting(String who) { this.who = who; } 
} 
! 
public class Greeter extends AbstractActor {{ 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchAny(unknown -> { 
println(“Unknown message " + unknown); 
}).build()); 
}} 
0. DEFINE 
X 
Define the message(s) the Actor 
should be able to respond to
public class Greeting implements Serializable { 
public final String who; 
public Greeting(String who) { this.who = who; } 
} 
! 
public class Greeter extends AbstractActor {{ 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchAny(unknown -> { 
println(“Unknown message " + unknown); 
}).build()); 
}} 
0. DEFINE 
X 
Define the message(s) the Actor 
should be able to respond to 
Define the Actor class
public class Greeting implements Serializable { 
public final String who; 
public Greeting(String who) { this.who = who; } 
} 
! 
public class Greeter extends AbstractActor {{ 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchAny(unknown -> { 
println(“Unknown message " + unknown); 
}).build()); 
}} 
0. DEFINE 
X 
Define the message(s) the Actor 
should be able to respond to 
Define the Actor class 
Define the Actor’s behavior
1. CREATE 
ActorSystem system = ActorSystem.create("MySystem"); 
! 
ActorRef greeter = 
system.actorOf(Props.create(Greeter.class), “greeter");
1. CREATE 
Create an Actor system 
ActorSystem system = ActorSystem.create("MySystem"); 
! 
ActorRef greeter = 
system.actorOf(Props.create(Greeter.class), “greeter");
1. CREATE 
Create an Actor system 
Actor configuration 
ActorSystem system = ActorSystem.create("MySystem"); 
! 
ActorRef greeter = 
system.actorOf(Props.create(Greeter.class), “greeter");
1. CREATE 
Create an Actor system 
Actor configuration 
ActorSystem system = ActorSystem.create("MySystem"); 
! 
ActorRef greeter = 
system.actorOf(Props.create(Greeter.class), “greeter"); 
Give it a name
1. CREATE 
Create an Actor system 
ActorSystem system = ActorSystem.create("MySystem"); 
! 
ActorRef greeter = 
system.actorOf(Props.create(Greeter.class), “greeter"); 
Give it a name 
Create the Actor 
Actor configuration
1. CREATE 
Create an Actor system 
ActorSystem system = ActorSystem.create("MySystem"); 
! 
ActorRef greeter = 
system.actorOf(Props.create(Greeter.class), “greeter"); 
Give it a name 
You get an ActorRef back 
Create the Actor 
Actor configuration
0. DEFINE 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
13 
case Greeting(who) => log.info(s"Hello ${who}") 
} 
}
0. DEFINE 
13 
Define the message(s) the Actor 
should be able to respond to 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info(s"Hello ${who}") 
} 
}
0. DEFINE 
13 
Define the message(s) the Actor 
should be able to respond to 
Define the Actor class 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info(s"Hello ${who}") 
} 
}
0. DEFINE 
13 
Define the message(s) the Actor 
should be able to respond to 
Define the Actor class 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info(s"Hello ${who}") 
} 
} 
Define the Actor’s behavior
1. CREATE 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info("Hello " + who) 
} 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter")
1. CREATE 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
Create an Actor system 
case Greeting(who) => log.info("Hello " + who) 
} 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter")
1. CREATE 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
Create an Actor system 
case Greeting(who) => log.info("Hello " } 
Actor configuration 
+ who) 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter")
1. CREATE 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info("Hello " + who) 
} 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 
Give it a name 
Create an Actor system 
Actor configuration
1. CREATE 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
Create an Actor system 
case Greeting(who) => log.info("Hello " } 
Actor configuration 
+ who) 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 
Give it a name 
Create the Actor
1. CREATE 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
Create an Actor system 
case Greeting(who) => log.info("Hello " } 
Actor configuration 
+ who) 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 
Give it a name 
You get an ActorRef bCarcekate the Actor
Actors can form hierarchies 
Guardian System Actor
Actors can form hierarchies 
Guardian System Actor 
system.actorOf(Props.create(Foo.class), “Foo”);
Actors can form hierarchies 
Foo 
Guardian System Actor 
system.actorOf(Props.create(Foo.class), “Foo”);
Actors can form hierarchies 
Foo 
Guardian System Actor 
context().actorOf(Props.create(A.class), “A”);
Actors can form hierarchies 
A 
Foo 
Guardian System Actor 
context().actorOf(Props.create(A.class), “A”);
Actors can form hierarchies 
A 
Foo Bar 
B 
C 
B 
E 
A 
D 
C 
Guardian System Actor
Actors can form hierarchies 
Guardian System Actor
Actors can form hierarchies 
Guardian System Actor 
system.actorOf(Props[Foo], “Foo”)
Actors can form hierarchies 
Foo 
Guardian System Actor 
system.actorOf(Props[Foo], “Foo”)
Actors can form hierarchies 
Foo 
Guardian System Actor 
context.actorOf(Props[A], “A”)
Actors can form hierarchies 
A 
Foo 
Guardian System Actor 
context.actorOf(Props[A], “A”)
Actors can form hierarchies 
A 
Foo Bar 
B 
C 
B 
E 
A 
D 
C 
Guardian System Actor
Name resolution—like a file-system 
A 
Foo Bar 
B 
C 
B 
E 
A 
D 
C 
Guardian System Actor
Name resolution—like a file-system 
A 
Foo Bar 
B 
C 
B 
E 
A 
D 
C 
/Foo 
Guardian System Actor
Name resolution—like a file-system 
A 
Foo Bar 
B 
C 
B 
E 
A 
D 
C 
/Foo 
/Foo/A 
Guardian System Actor
Name resolution—like a file-system 
A 
Foo Bar 
B 
C 
B 
E 
A 
D 
C 
/Foo 
/Foo/A 
/Foo/A/B 
Guardian System Actor
Name resolution—like a file-system 
A 
Foo Bar 
B 
C 
B 
E 
A 
D 
C 
/Foo 
/Foo/A 
/Foo/A/B 
/Foo/A/D 
Guardian System Actor
2. SEND 
X 
greeter.tell(new Greeting("Charlie Parker”), sender);
2. SEND 
X 
greeter.tell(new Greeting("Charlie Parker”), sender); 
Send the message asynchronously
2. SEND 
X 
Pass in the sender ActorRef 
greeter.tell(new Greeting("Charlie Parker”), sender); 
Send the message asynchronously
Bring it together 
X 
public class Greeting implements Serializable { 
public final String who; 
public Greeting(String who) { this.who = who; } 
} 
public class Greeter extends AbstractActor {{ 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchAny(unknown -> { 
println(“Unknown message " + unknown); 
}).build()); 
} 
}} 
! 
ActorSystem system = ActorSystem.create("MySystem"); 
ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter"); 
greeter.tell(new Greeting(“Charlie Parker”));
2. SEND 
17 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info(s”Hello ${who}") 
} 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 
greeter ! Greeting("Charlie Parker")
2. SEND 
17 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info(s”Hello ${who}") 
} 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 
greeter ! Greeting("Charlie Parker") 
Send the message asynchronously
Bring it together 
18 
case class Greeting(who: String) 
! 
class GreetingActor extends Actor with ActorLogging { 
def receive = { 
case Greeting(who) => log.info(s”Hello ${who}") 
} 
} 
! 
val system = ActorSystem("MySystem") 
val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 
greeter ! Greeting("Charlie Parker")
DEMO TIME A simple game of ping pong
3. BECOME 
X 
public class Greeter extends AbstractActor { 
public Greeter { 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchEquals(“stop" -> { 
!!!! }).build(); 
} 
}
3. BECOME 
X 
public class Greeter extends AbstractActor { 
public Greeter { 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchEquals(“stop" -> { 
!!!! }).build(); 
} 
} 
context().become(ReceiveBuilder.
3. BECOME 
X 
public class Greeter extends AbstractActor { 
public Greeter { 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchEquals(“stop" -> { 
!!!! }).build(); 
} 
} 
Change the behavior 
context().become(ReceiveBuilder.
3. BECOME 
X 
public class Greeter extends AbstractActor { 
public Greeter { 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchEquals(“stop" -> { 
!!!! }).build(); 
} 
} 
Change the behavior 
context().become(ReceiveBuilder. 
match(Greeting.class, m -> {
3. BECOME 
X 
public class Greeter extends AbstractActor { 
public Greeter { 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchEquals(“stop" -> { 
!!!! }).build(); 
} 
} 
Change the behavior 
context().become(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Go Away!”);
3. BECOME 
X 
public class Greeter extends AbstractActor { 
public Greeter { 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchEquals(“stop" -> { 
!!!! }).build(); 
} 
} 
Change the behavior 
context().become(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Go Away!”); 
}).build());
3. BECOME 
X 
public class Greeter extends AbstractActor { 
public Greeter { 
receive(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Hello " + m.who); 
}). 
matchEquals(“stop" -> { 
!!!! }).build(); 
} 
} 
Change the behavior 
context().become(ReceiveBuilder. 
match(Greeting.class, m -> { 
println(“Go Away!”); 
}).build());
3. BECOME 
19 
class GreetingActor extends Actor with ActorLogging { 
def receive = happy 
! 
val happy: Receive = { 
case Greeting(who) => log.info(s”Hello ${who}") 
case Angry => context become angry 
} 
! 
val angry: Receive = { 
case Greeting(_) => log.info("Go away!") 
case Happy => context become happy 
} 
}
3. BECOME 
19 
class GreetingActor extends Actor with ActorLogging { 
def receive = happy 
! 
val happy: Receive = { 
case Greeting(who) => log.info(s”Hello ${who}") 
case Angry => context become angry 
} 
! 
val angry: Receive = { 
case Greeting(_) => log.info("Go away!") 
case Happy => context become happy 
} 
} 
Redefine the behavior
Reactive applications are architected 
to handle failure at all levels.
Resilient 
• Failure is embraced as a natural state in the app lifecycle 
• Resilience is a first-class construct 
• Failure is detected, isolated, and managed 
• Applications self heal 
21 
“The Typesafe Reactive Platform helps us maintain a very 
aggressive development and deployment cycle, all in a fail-forward manner. 
It’s now the default choice for developing all new services.” 
Peter Hausel, VP Engineering, Gawker Media
Think Vending Machine
Think Vending Machine 
Coffee 
Programmer Machine
Think Vending Machine 
Coffee 
Inserts coins 
Programmer Machine
Think Vending Machine 
Coffee 
Inserts coins 
Add more coins 
Programmer Machine
Think Vending Machine 
Coffee 
Inserts coins 
Add more coins 
Programmer Machine 
Gets coffee
Think Vending Machine 
Coffee 
Programmer Machine