diff --git a/dub.selections.json b/dub.selections.json
index 714698e..1b3d1a1 100644
--- a/dub.selections.json
+++ b/dub.selections.json
@@ -6,7 +6,7 @@
 		"botan-math": "1.0.3",
 		"ddmp": "0.0.1-0.dev.3",
 		"diet-ng": "1.5.0",
-		"eventcore": "0.8.39",
+		"eventcore": "0.8.40",
 		"fluent-asserts": "0.12.3",
 		"libasync": "0.8.3",
 		"libdparse": "0.8.8",
@@ -14,9 +14,9 @@
 		"memutils": "0.4.13",
 		"mir-linux-kernel": "1.0.1",
 		"openssl": "1.1.6+1.0.1g",
-		"stdx-allocator": "2.77.4",
+		"stdx-allocator": "2.77.5",
 		"taggedalgebraic": "0.10.12",
-		"vibe-core": "1.4.5",
+		"vibe-core": "1.4.6",
 		"vibe-d": "0.8.4"
 	}
-}
\ No newline at end of file
+}
diff --git a/source/d_webservice_example/application.d b/source/d_webservice_example/application.d
index 3e7961a..b6fa416 100644
--- a/source/d_webservice_example/application.d
+++ b/source/d_webservice_example/application.d
@@ -1,12 +1,15 @@
 module d_webservice_example.application;
 
-import aermicioi.aedi : locate, singleton;
-import vibe.vibe;
+import aermicioi.aedi : Container, locate, singleton;
+import vibe.http.router : URLRouter;
 
 void main() @safe
 {
     import d_webservice_example.component_registration : registerComponents;
-    import d_webservice_example.controller.todo_controller : TodoController;
+    import vibe.core.core : runApplication;
+    import vibe.http.server : HTTPServerSettings, listenHTTP;
+
+    setupLogging;
 
     auto container = singleton;
     scope (exit)
@@ -15,12 +18,38 @@ void main() @safe
     container.registerComponents;
     container.instantiate;
 
-    auto router = new URLRouter;
-    router.registerRestInterface(container.locate!TodoController);
     auto settings = new HTTPServerSettings;
     settings.port = 8080;
     settings.bindAddresses = ["::", "0.0.0.0"];
+
+    auto router = setupRouter(container);
     listenHTTP(settings, router);
 
     runApplication;
 }
+
+void setupLogging() nothrow @safe
+{
+    import vibe.core.log : setLogFormat, FileLogger;
+
+    debug
+    {
+        import vibe.core.log : LogLevel, setLogLevel;
+
+        setLogLevel(LogLevel.diagnostic);
+    }
+    setLogFormat(FileLogger.Format.threadTime, FileLogger.Format.threadTime);
+}
+
+URLRouter setupRouter(Container container) @safe
+{
+    import d_webservice_example.controller.todo_controller : TodoController;
+    import d_webservice_example.controller.todo_notification_controller : TodoNotificationController;
+    import vibe.web.rest : registerRestInterface;
+    import vibe.web.web : registerWebInterface;
+
+    auto router = new URLRouter;
+    router.registerRestInterface(container.locate!TodoController);
+    router.registerWebInterface(container.locate!TodoNotificationController);
+    return router;
+}
diff --git a/source/d_webservice_example/business/todo_notification_service.d b/source/d_webservice_example/business/todo_notification_service.d
new file mode 100644
index 0000000..548eb5a
--- /dev/null
+++ b/source/d_webservice_example/business/todo_notification_service.d
@@ -0,0 +1,43 @@
+module d_webservice_example.business.todo_notification_service;
+
+class TodoNotificationService
+{
+    import d_webservice_example.data.todo_notification : TodoNotification;
+    import d_webservice_example.enums.todo_notification_type : TodoNotificationType;
+    import d_webservice_example.mapper.todo_mapper : asTodoTO;
+    import d_webservice_example.model.todo : Todo;
+    import std.traits : EnumMembers;
+
+private:
+    bool[void delegate(scope TodoNotification) @safe] listeners;
+
+public:
+    this() const nothrow pure @nogc @safe
+    {
+    }
+
+    void registerListener(scope void delegate(scope const TodoNotification) @safe listener) @safe
+    {
+        listeners[listener] = true;
+    }
+
+    void unRegisterListener(scope void delegate(scope const TodoNotification) @safe listener) @safe
+    {
+        listeners.remove(listener);
+    }
+
+    static foreach (method; EnumMembers!TodoNotificationType)
+    {
+        import std.conv: to;
+        import std.format : format;
+        mixin(format!q{
+            void onTodo%1$sd(const Todo todo) @safe
+            {
+                import std.algorithm.iteration : each;
+
+                immutable todoChange = TodoNotification(TodoNotificationType.%1$s, todo);
+                listeners.byKey.each!(listener => listener(todoChange));
+            }
+        }(method.to!string));
+    }
+}
diff --git a/source/d_webservice_example/business/todo_service.d b/source/d_webservice_example/business/todo_service.d
index 346ca43..9bb44cf 100644
--- a/source/d_webservice_example/business/todo_service.d
+++ b/source/d_webservice_example/business/todo_service.d
@@ -5,7 +5,9 @@ import std.uuid : UUID, randomUUID;
 
 class TodoService
 {
+    import d_webservice_example.business.todo_notification_service : TodoNotificationService;
     import d_webservice_example.data.todo_update_do : TodoUpdateDO;
+    import vibe.core.log : logInfo;
 
 private:
     TodoRepository todoRepository;
@@ -17,10 +19,12 @@ public:
         this.todoRepository = todoRepository;
     }
 
-    Todo createTodo(Todo newTodo) @safe
+    Todo createTodo(const Todo newTodo) @safe
     {
-        immutable todo = Todo(newTodo.title, newTodo.content, randomUUID);
-        return todoRepository.save(todo);
+        immutable createdTodo = todoRepository.save(Todo(newTodo.title,
+                newTodo.content, randomUUID));
+        logInfo("Created todo %s", createdTodo);
+        return createdTodo;
     }
 
     Todo[] getAllTodos() @safe
@@ -46,13 +50,17 @@ public:
         if (todoUpdate.content != null)
             todo.content = todoUpdate.content;
 
-        return todoRepository.save(todo);
+        immutable updatedTodo = todoRepository.save(todo);
+        logInfo("Updated todo %s", updatedTodo);
+        return updatedTodo;
     }
 
-    void deleteTodo(UUID uuid) @safe
+    Todo deleteTodo(UUID uuid) @safe
     {
         immutable todo = getTodoByUuid(uuid);
         todoRepository.remove(todo);
+        logInfo("Deleted todo %s", todo);
+        return todo;
     }
 }
 
diff --git a/source/d_webservice_example/component_registration.d b/source/d_webservice_example/component_registration.d
index 44bf688..3b409d1 100644
--- a/source/d_webservice_example/component_registration.d
+++ b/source/d_webservice_example/component_registration.d
@@ -4,11 +4,20 @@ import aermicioi.aedi;
 
 void registerComponents(ConfigurableContainer container) @safe
 {
+    import d_webservice_example.business.todo_notification_service : TodoNotificationService;
     import d_webservice_example.business.todo_service : TodoRepository, TodoService;
     import d_webservice_example.controller.todo_controller : TodoController;
+    import d_webservice_example.controller.todo_notification_controller : TodoNotificationController;
     import d_webservice_example.dataaccess.in_memory_todo_repository : InMemoryTodoRepository;
+    import d_webservice_example.facade.todo_facade : TodoFacade;
 
-    container.configure.register!(TodoRepository, InMemoryTodoRepository);
-    container.configure.register!TodoService.autowire;
-    container.configure.register!TodoController.autowire;
+    with (container.configure)
+    {
+        register!TodoService.autowire;
+        register!TodoNotificationService.autowire;
+        register!TodoController.autowire;
+        register!TodoNotificationController.autowire;
+        register!(TodoRepository, InMemoryTodoRepository).autowire;
+        register!TodoFacade.autowire;
+    }
 }
diff --git a/source/d_webservice_example/controller/todo_controller.d b/source/d_webservice_example/controller/todo_controller.d
index ae984c7..0100a17 100644
--- a/source/d_webservice_example/controller/todo_controller.d
+++ b/source/d_webservice_example/controller/todo_controller.d
@@ -26,25 +26,26 @@ interface TodoApi
 
 class TodoController : TodoApi
 {
-    import d_webservice_example.business.todo_service : TodoService;
+    import d_webservice_example.facade.todo_facade : TodoFacade;
     import d_webservice_example.mapper.todo_mapper : asTodoTO;
+    import vibe.core.log : logDiagnostic;
 
 private:
-    TodoService todoService;
+    TodoFacade todoFacade;
 
 public:
 
-    this(TodoService todoService) nothrow pure @nogc @safe
+    this(TodoFacade todoFacade) nothrow pure @nogc @safe
     {
-        this.todoService = todoService;
+        this.todoFacade = todoFacade;
     }
 
-    // TODO: validation
     override TodoTO addTodo(string title, string content) @safe
     {
         import d_webservice_example.model.todo : Todo;
 
-        return todoService.createTodo(Todo(title, content)).asTodoTO;
+        logDiagnostic("Received request to add a todo with title '%s' and content '%s'", title, content);
+        return todoFacade.createTodo(Todo(title, content)).asTodoTO;
     }
 
     override TodoTO[] getTodos() @safe
@@ -52,29 +53,35 @@ public:
         import std.algorithm.iteration : map;
         import std.array : array;
 
-        return todoService.getAllTodos.map!asTodoTO.array;
+        logDiagnostic("Received request to get all todos");
+        return todoFacade.getAllTodos.map!asTodoTO.array;
     }
 
     override TodoTO getTodo(UUID _uuid) @safe
     {
-        return todoService.getTodoByUuid(_uuid).asTodoTO;
+
+        logDiagnostic("Received request to get todo '%s'", _uuid);
+        return todoFacade.getTodoByUuid(_uuid).asTodoTO;
     }
 
     override TodoTO updateTodo(UUID _uuid, Nullable!string title, Nullable!string content) @safe
     {
         import d_webservice_example.data.todo_update_do : TodoUpdateDO;
 
+        logDiagnostic("Received request to update todo '%s' with title '%s' and content '%s'",
+                _uuid, title, content);
         TodoUpdateDO update;
         if (!title.isNull)
             update.title = title.get;
         if (!content.isNull)
             update.content = content.get;
 
-        return todoService.updateTodo(_uuid, update).asTodoTO;
+        return todoFacade.updateTodo(_uuid, update).asTodoTO;
     }
 
     override void deleteTodo(UUID _uuid) @safe
     {
-        todoService.deleteTodo(_uuid);
+        logDiagnostic("Received request to delete todo '%s'", _uuid);
+        todoFacade.deleteTodo(_uuid);
     }
 }
diff --git a/source/d_webservice_example/controller/todo_notification_controller.d b/source/d_webservice_example/controller/todo_notification_controller.d
new file mode 100644
index 0000000..3d307c6
--- /dev/null
+++ b/source/d_webservice_example/controller/todo_notification_controller.d
@@ -0,0 +1,55 @@
+module d_webservice_example.controller.todo_notification_controller;
+
+import vibe.http.websockets : WebSocket;
+import vibe.web.web : path;
+
+@path("/api/v1/rt")
+class TodoNotificationController
+{
+    import d_webservice_example.business.todo_notification_service : TodoNotificationService;
+
+private:
+    TodoNotificationService todoNotificationService;
+
+public:
+    this(TodoNotificationService todoNotificationService) nothrow pure @nogc @safe
+    {
+        this.todoNotificationService = todoNotificationService;
+    }
+
+    @path("/todos") void getWebsocket(scope WebSocket socket) @safe
+    {
+        import d_webservice_example.data.todo_notification : TodoNotification;
+        import d_webservice_example.transport.todo_notification_cto : TodoNotificationCTO;
+        import vibe.core.log : logDiagnostic;
+
+        logDiagnostic("Received request for todo notifications via web socket connection");
+
+        auto callback = (scope const TodoNotification todoNotification) {
+            import d_webservice_example.mapper.todo_notification_mapper : asTodoNotificationCTO;
+            import vibe.data.json : serializeToJsonString;
+
+            logDiagnostic("Sending todo notification to client");
+            socket.send(todoNotification.asTodoNotificationCTO.serializeToJsonString);
+        };
+        todoNotificationService.registerListener(callback);
+
+        dropWebsocketInput(socket);
+
+        todoNotificationService.unRegisterListener(callback);
+        logDiagnostic("Client disconnected from web socket connection: %s(%s)",
+                socket.closeReason, socket.closeCode);
+    }
+}
+
+private:
+
+void dropWebsocketInput(scope WebSocket socket) @safe
+{
+    while (socket.connected)
+    {
+        socket.waitForData;
+        if (socket.connected)
+            socket.receive((scope IncomingWebSocketMessage) {});
+    }
+}
diff --git a/source/d_webservice_example/data/todo_notification.d b/source/d_webservice_example/data/todo_notification.d
new file mode 100644
index 0000000..f3a897c
--- /dev/null
+++ b/source/d_webservice_example/data/todo_notification.d
@@ -0,0 +1,10 @@
+module d_webservice_example.data.todo_notification;
+
+import d_webservice_example.enums.todo_notification_type : TodoNotificationType;
+import d_webservice_example.model.todo : Todo;
+
+struct TodoNotification
+{
+    TodoNotificationType type;
+    Todo todo;
+}
diff --git a/source/d_webservice_example/dataaccess/in_memory_todo_repository.d b/source/d_webservice_example/dataaccess/in_memory_todo_repository.d
index 3a4772c..8e81146 100644
--- a/source/d_webservice_example/dataaccess/in_memory_todo_repository.d
+++ b/source/d_webservice_example/dataaccess/in_memory_todo_repository.d
@@ -17,6 +17,11 @@ private:
     Todo[string] todos;
 
 public:
+
+    this() nothrow pure @nogc @safe
+    {
+    }
+
     override Todo save(Todo todo)
     {
         import std.range.primitives : empty;
diff --git a/source/d_webservice_example/enums/todo_notification_type.d b/source/d_webservice_example/enums/todo_notification_type.d
new file mode 100644
index 0000000..2d2fe7e
--- /dev/null
+++ b/source/d_webservice_example/enums/todo_notification_type.d
@@ -0,0 +1,8 @@
+module d_webservice_example.enums.todo_notification_type;
+
+enum TodoNotificationType
+{
+    Create = "create",
+    Update = "update",
+    Delete = "delete"
+}
diff --git a/source/d_webservice_example/facade/todo_facade.d b/source/d_webservice_example/facade/todo_facade.d
new file mode 100644
index 0000000..783bd48
--- /dev/null
+++ b/source/d_webservice_example/facade/todo_facade.d
@@ -0,0 +1,51 @@
+module d_webservice_example.facade.todo_facade;
+
+class TodoFacade
+{
+    import d_webservice_example.business.todo_notification_service : TodoNotificationService;
+    import d_webservice_example.business.todo_service : TodoService;
+    import d_webservice_example.data.todo_update_do : TodoUpdateDO;
+    import d_webservice_example.model.todo : Todo;
+    import std.uuid : UUID;
+
+private:
+    TodoNotificationService todoNotificationService;
+    TodoService todoService;
+
+public:
+    this(TodoNotificationService todoNotificationService, TodoService todoService) nothrow pure @nogc @safe
+    {
+        this.todoNotificationService = todoNotificationService;
+        this.todoService = todoService;
+    }
+
+    Todo createTodo(Todo newTodo) @safe
+    {
+        immutable todo = todoService.createTodo(newTodo);
+        todoNotificationService.onTodoCreated(todo);
+        return todo;
+    }
+
+    Todo[] getAllTodos() @safe
+    {
+        return todoService.getAllTodos;
+    }
+
+    Todo getTodoByUuid(const UUID uuid) @safe
+    {
+        return todoService.getTodoByUuid(uuid);
+    }
+
+    Todo updateTodo(UUID uuid, const TodoUpdateDO todoUpdate) @safe
+    {
+        immutable todo = todoService.updateTodo(uuid, todoUpdate);
+        todoNotificationService.onTodoUpdated(todo);
+        return todo;
+    }
+
+    void deleteTodo(UUID uuid) @safe
+    {
+        immutable todo = todoService.deleteTodo(uuid);
+        todoNotificationService.onTodoDeleted(todo);
+    }
+}
diff --git a/source/d_webservice_example/mapper/todo_mapper.d b/source/d_webservice_example/mapper/todo_mapper.d
index e761df5..5cd06ac 100644
--- a/source/d_webservice_example/mapper/todo_mapper.d
+++ b/source/d_webservice_example/mapper/todo_mapper.d
@@ -3,7 +3,7 @@ module d_webservice_example.mapper.todo_mapper;
 import d_webservice_example.model.todo : Todo;
 import d_webservice_example.transport.todo_to : TodoTO;
 
-TodoTO asTodoTO(Todo todo) nothrow pure @safe @nogc
+TodoTO asTodoTO(const Todo todo) nothrow pure @safe @nogc
 {
     return TodoTO(todo.uuid, todo.title, todo.content);
 }
diff --git a/source/d_webservice_example/mapper/todo_notification_mapper.d b/source/d_webservice_example/mapper/todo_notification_mapper.d
new file mode 100644
index 0000000..fb18913
--- /dev/null
+++ b/source/d_webservice_example/mapper/todo_notification_mapper.d
@@ -0,0 +1,11 @@
+module d_webservice_example.mapper.todo_notification_mapper;
+
+import d_webservice_example.data.todo_notification : TodoNotification;
+import d_webservice_example.transport.todo_notification_cto : TodoNotificationCTO;
+
+TodoNotificationCTO asTodoNotificationCTO(const TodoNotification todoNotification) nothrow pure @safe @nogc
+{
+    import d_webservice_example.mapper.todo_mapper : asTodoTO;
+
+    return TodoNotificationCTO(todoNotification.type, todoNotification.todo.asTodoTO);
+}
diff --git a/source/d_webservice_example/model/todo.d b/source/d_webservice_example/model/todo.d
index e7e36d4..9543d75 100644
--- a/source/d_webservice_example/model/todo.d
+++ b/source/d_webservice_example/model/todo.d
@@ -3,7 +3,6 @@ module d_webservice_example.model.todo;
 struct Todo
 {
     import std.uuid : UUID;
-    import vibe.data.serialization : name;
 
     this(string title, string content) nothrow pure @safe @nogc
     {
@@ -28,9 +27,6 @@ struct Todo
 
     string title;
     string content;
-
     UUID uuid;
-
-    @name("_id")
     string id;
 }
diff --git a/source/d_webservice_example/transport/todo_notification_cto.d b/source/d_webservice_example/transport/todo_notification_cto.d
new file mode 100644
index 0000000..de8c0b7
--- /dev/null
+++ b/source/d_webservice_example/transport/todo_notification_cto.d
@@ -0,0 +1,10 @@
+module d_webservice_example.transport.todo_notification_cto;
+
+import d_webservice_example.enums.todo_notification_type : TodoNotificationType;
+import d_webservice_example.transport.todo_to : TodoTO;
+
+struct TodoNotificationCTO
+{
+    TodoNotificationType type;
+    TodoTO todo;
+}