diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml
deleted file mode 100644
index 60f4323f..00000000
--- a/.github/workflows/clippy.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-on: pull_request
-
-name: Clippy Check
-jobs:
-  clippy_check:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@master
-      - uses: actions-rs/toolchain@v1
-        with:
-          toolchain: nightly
-          components: clippy
-          override: true
-      - uses: actions-rs/clippy-check@v1
-        with:
-          token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml
index a700d30d..9bb85e89 100644
--- a/.github/workflows/miri.yml
+++ b/.github/workflows/miri.yml
@@ -14,7 +14,7 @@ jobs:
       - name: Install
         uses: actions-rs/toolchain@v1
         with:
-          toolchain: nightly-2020-06-22
+          toolchain: nightly-2021-03-20
           override: true
       - uses: davidB/rust-cargo-make@v1
         with:
@@ -24,13 +24,4 @@ jobs:
           RUST_BACKTRACE: full
           RUST_LOG: 'trace'
         run: |
-          rustup component add miri
-          cargo miri setup
-          cargo clean
-          # Do some Bastion shake
-          cd src/bastion && \
-            cargo miri test --features lever/nightly -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -- dispatcher && \
-            cargo miri test --features lever/nightly -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -- path && \
-            cargo miri test --features lever/nightly -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -- broadcast && \
-            cargo miri test --features lever/nightly -- -Zmiri-disable-isolation -Zmiri-ignore-leaks -- children_ref && \
-            cd -
+          tools/miri.sh
diff --git a/.github/workflows/sanitizers.yml b/.github/workflows/sanitizers.yml
index 553f631d..0578794d 100644
--- a/.github/workflows/sanitizers.yml
+++ b/.github/workflows/sanitizers.yml
@@ -15,7 +15,7 @@ jobs:
       - name: Install
         uses: actions-rs/toolchain@v1
         with:
-          toolchain: nightly-2020-03-08
+          toolchain: nightly-2021-03-20
           override: true
       - uses: davidB/rust-cargo-make@v1
         with:
diff --git a/README.md b/README.md
index e465c6ad..ad1df3ff 100644
--- a/README.md
+++ b/README.md
@@ -2,82 +2,73 @@
   <img src="https://github.com/bastion-rs/bastion/blob/master/img/bastion.png"><br>
 </div>
 
------------------
-
-<h1 align="center">Highly-available Distributed Fault-tolerant Runtime</h1>
+---
 
-<table align=left style='float: left; margin: 4px 10px 0px 0px; border: 1px solid #000000;'>
-<tr>
-  <td>Latest Release</td>
-  <td>
-    <a href="https://crates.io/crates/bastion">
-    <img alt="Crates.io" src="https://img.shields.io/crates/v/bastion.svg?style=popout-square">
-    </a>
-  </td>
-</tr>
-<tr>
-  <td></td>
-</tr>
-<tr>
-  <td>License</td>
-  <td>
-    <a href="https://github.com/bastion-rs/bastion/blob/master/LICENSE">
-    <img alt="Crates.io" src="https://img.shields.io/crates/l/bastion.svg?style=popout-square">
-    </a>
-</td>
-</tr>
-<tr>
-  <td>Doc [Bastion]</td>
-  <td>
-    <a href="https://docs.rs/bastion">
-    <img alt="Documentation (Bastion)" src="https://img.shields.io/badge/rustdoc-bastion-blue.svg" />
-    </a>
-  </td>
-</tr>
-<tr>
+<table>
+  <tr>
+    <td>Latest Release</td>
+    <td>
+      <a href="https://crates.io/crates/bastion">
+      <img alt="Crates.io" src="https://img.shields.io/crates/v/bastion.svg?style=popout-square">
+      </a>
+    </td>
+    <td>License</td>
+    <td>
+      <a href="https://github.com/bastion-rs/bastion/blob/master/LICENSE">
+      <img alt="Crates.io" src="https://img.shields.io/crates/l/bastion.svg?style=popout-square">
+      </a>
+    </td>
+  </tr>
+  <tr>
+    <td>Doc [Bastion]</td>
+    <td>
+      <a href="https://docs.rs/bastion">
+      <img alt="Documentation (Bastion)" src="https://img.shields.io/badge/rustdoc-bastion-blue.svg" />
+      </a>
+    </td>
+    <td>Downloads</td>
+    <td>
+      <a href="https://crates.io/crates/bastion">
+      <img alt="Crates.io" src="https://img.shields.io/crates/d/bastion.svg?style=popout-square">
+      </a>
+    </td>
+  </tr>
+  <tr>
   <td>Doc [Bastion Executor]</td>
-  <td>
-    <a href="https://docs.rs/bastion-executor">
-    <img alt="Documentation (Bastion Executor)" src="https://img.shields.io/badge/rustdoc-bastion_executor-blue.svg" />
-    </a>
-  </td>
-</tr>
-<tr>
-  <td>Doc [LightProc]</td>
-  <td>
-    <a href="https://docs.rs/lightproc">
-    <img alt="Documentation (LightProc)" src="https://img.shields.io/badge/rustdoc-lightproc-blue.svg" />
-    </a>
-  </td>
-</tr>
-<tr>
-  <td>Build Status</td>
-  <td>
-    <a href="https://github.com/bastion-rs/bastion/actions">
-    <img alt="Build Status" src="https://github.com/bastion-rs/bastion/workflows/CI/badge.svg" />
-    </a>
-  </td>
-</tr>
-<tr>
-  <td>Downloads</td>
-  <td>
-    <a href="https://crates.io/crates/bastion">
-    <img alt="Crates.io" src="https://img.shields.io/crates/d/bastion.svg?style=popout-square">
-    </a>
-  </td>
-</tr>
-<tr>
-	<td>Discord</td>
-	<td>
-		<a href="https://discord.gg/DqRqtRT">
-		<img src="https://img.shields.io/discord/628383521450360842.svg?logo=discord" />
-		</a>
-	</td>
-</tr>
+    <td>
+      <a href="https://docs.rs/bastion-executor">
+      <img alt="Documentation (Bastion Executor)" src="https://img.shields.io/badge/rustdoc-bastion_executor-blue.svg" />
+      </a>
+    </td>
+    <td>Discord</td>
+    <td>
+      <a href="https://discord.gg/DqRqtRT">
+      <img src="https://img.shields.io/discord/628383521450360842.svg?logo=discord" />
+      </a>
+    </td>
+  </tr>
+  <tr>
+  </tr>
+  <tr>
+    <td>Doc [LightProc]</td>
+    <td>
+      <a href="https://docs.rs/lightproc">
+      <img alt="Documentation (LightProc)" src="https://img.shields.io/badge/rustdoc-lightproc-blue.svg" />
+      </a>
+    </td>
+    <td>Build Status</td>
+    <td>
+      <a href="https://github.com/bastion-rs/bastion/actions">
+      <img alt="Build Status" src="https://github.com/bastion-rs/bastion/workflows/CI/badge.svg" />
+      </a>
+    </td>
+  </tr>
 </table>
 
 ---
 
+<h1 align="center">Highly-available Distributed Fault-tolerant Runtime</h1>
+
 Bastion is a highly-available, fault-tolerant runtime system with dynamic, dispatch-oriented, lightweight process model. It supplies actor-model-like concurrency with a lightweight process implementation and utilizes all of the system resources efficiently guaranteeing of at-most-once message delivery.
 
 ---
@@ -87,6 +78,23 @@ Bastion is a highly-available, fault-tolerant runtime system with dynamic, dispa
 Bastion comes with a default one-for-one strategy root supervisor.
 You can use this to launch automatically supervised tasks.
 
+## Get Started
+
+Include bastion to your project with:
+```toml
+bastion = "0.4"
+```
+
+### Documentation
+
+Official documentation is hosted on [docs.rs](https://docs.rs/bastion).
+
+### Examples
+
+Check the [getting started example](https://github.com/bastion-rs/bastion/blob/master/src/bastion/examples/getting_started.rs) in <code>bastion/examples</code>
+
+[Examples](https://github.com/bastion-rs/bastion/blob/master/src/bastion/examples) cover possible use cases of the crate.
+
 ## Features
 * Message-based communication makes this project a lean mesh of actor system.
     * Without web servers, weird shenanigans, forced trait implementations, and static dispatch.
@@ -144,43 +152,23 @@ It's independent of it's framework implementation. It uses lightproc to encapsul
 ### [Agnostik](https://github.com/bastion-rs/agnostik)
 Agnostik is a layer between your application and the executor for your async stuff. It lets you switch the executors smooth and easy without having to change your applications code. Valid features are `runtime_bastion` (default), `runtime_tokio`, `runtime_asyncstd` and `runtime_nostd` (coming soon).
 
-## Get Started
-Check the [getting started example](https://github.com/bastion-rs/bastion/blob/master/src/bastion/examples/getting_started.rs) in <code>bastion/examples</code>
-
-[Examples](https://github.com/bastion-rs/bastion/blob/master/src/bastion/examples) cover possible use cases of the crate.
-
-Include bastion to your project with:
-```toml
-bastion = "0.4"
-```
-
-For more information please check [Bastion Documentation](https://docs.rs/bastion)
-
 ## Architecture of the Runtime
 Runtime is structured by the user. Only root supervision comes in batteries-included fashion.
 Worker code, worker group redundancy, supervisors and their supervision strategies are defined by the user.
 
-## License
-
-Licensed under either of
-
- * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
-
-at your option.
-
-## Documentation
+Supervision strategies define how child actor failures are handled, how often a child can fail, and how long to wait before a child actor is recreated. As the name suggests, One-For-One strategy means the supervision strategy is applied only to the failed child. All-For-One strategy means that the supervision strategy is applied to all the actor siblings as well. One-for-one supervision is used at the root supervisor, while child groups may have different strategies like rest-for-one or one-for-all.
 
-Official documentation is hosted on [docs.rs](https://docs.rs/bastion).
+![Bastion Architecture](img/bastion-architecture.png)
 
-## Getting Help
+## Community
+### Getting Help
 Please head to our [Discord](https://discord.gg/DqRqtRT) or use [StackOverflow](https://stackoverflow.com/questions/tagged/bastion)
 
-## Discussion and Development
+### Discussion and Development
 We use [Discord](https://discord.gg/DqRqtRT) for development discussions. Also please don't hesitate to open issues on GitHub ask for features, report bugs, comment on design and more!
 More interaction and more ideas are better!
 
-## Contributing to Bastion [![Open Source Helpers](https://www.codetriage.com/bastion-rs/bastion/badges/users.svg)](https://www.codetriage.com/bastion-rs/bastion)
+### Contributing to Bastion [![Open Source Helpers](https://www.codetriage.com/bastion-rs/bastion/badges/users.svg)](https://www.codetriage.com/bastion-rs/bastion)
 
 All contributions, bug reports, bug fixes, documentation improvements, enhancements and ideas are welcome.
 
@@ -188,6 +176,13 @@ A detailed overview on how to contribute can be found in the  [CONTRIBUTING guid
 
 ## License
 
+Licensed under either of
+
+ * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
 [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbastion-rs%2Fbastion.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fbastion-rs%2Fbastion?ref=badge_large)
 
 [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbastion-rs%2Fbastion.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fbastion-rs%2Fbastion?ref=badge_shield)
diff --git a/img/bastion-architecture.png b/img/bastion-architecture.png
new file mode 100644
index 00000000..84ad4b0c
Binary files /dev/null and b/img/bastion-architecture.png differ
diff --git a/src/bastion-executor/Cargo.toml b/src/bastion-executor/Cargo.toml
index af659711..4e1c6143 100644
--- a/src/bastion-executor/Cargo.toml
+++ b/src/bastion-executor/Cargo.toml
@@ -5,7 +5,7 @@ name = "bastion-executor"
 # - Update CHANGELOG.md.
 #   - npm install -g auto-changelog && auto-changelog at the root
 # - Create "v0.x.y" git tag at the root of the project.
-version = "0.3.7-alpha.0"
+version = "0.4.1"
 description = "Cache affine NUMA-aware executor for Rust"
 authors = ["Mahmut Bulut <vertexclique@gmail.com>"]
 keywords = ["fault-tolerant", "runtime", "actor", "system"]
@@ -25,34 +25,41 @@ travis-ci = { repository = "bastion-rs/bastion", branch = "master" }
 maintenance = { status = "actively-developed" }
 
 [features]
-unstable = ["numanji", "allocator-suite", "jemallocator"]
+unstable = []
+tokio-runtime = ["tokio"]
 
 [dependencies]
-lightproc = "0.3.5"
 bastion-utils = "0.3.2"
+# lightproc = "0.3"
+lightproc =  { git = "https://github.com/bastion-rs/bastion.git" }
 # lightproc = { path = "../lightproc" }
 # bastion-utils = { path = "../bastion-utils" }
 
-crossbeam-utils = "0.7"
-crossbeam-channel = "0.4"
-crossbeam-epoch = "0.8"
+crossbeam-utils = "0.8"
+crossbeam-channel = "0.5"
+crossbeam-epoch = "0.9"
 lazy_static = "1.4"
 libc = "0.2"
 num_cpus = "1.13"
 pin-utils = "0.1.0"
 
 # Allocator
-numanji = { version = "^0.1", optional = true, default-features = false }
-allocator-suite = { version = "^0.1", optional = true, default-features = false }
-arrayvec = { version = "0.5.1", features = ["array-sizes-129-255"]}
+arrayvec = { version = "0.7.0" }
 futures-timer = "3.0.2"
+once_cell = "1.4.0"
+lever = "0.1"
+tracing = "0.1.19"
+crossbeam-queue = "0.3.0"
 
-[target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies]
-jemallocator = { version = "^0.3", optional = true, default-features = false }
+# Feature tokio
+tokio = {version = "1.1", features = ["rt", "rt-multi-thread"], optional = true }
 
 [target.'cfg(target_os = "windows")'.dependencies]
 winapi = { version = "^0.3.8", features = ["basetsd"] }
 
 [dev-dependencies]
-proptest = "^0.10"
+tokio = {version = "1.1", features = ["rt", "rt-multi-thread", "macros"] }
+tokio-test = "0.4.0"
+proptest = "^1.0"
 futures = "0.3.5"
+tracing-subscriber = "0.2.11"
diff --git a/src/bastion-executor/benches/blocking.rs b/src/bastion-executor/benches/blocking.rs
index df01bda4..6c5a6ffd 100644
--- a/src/bastion-executor/benches/blocking.rs
+++ b/src/bastion-executor/benches/blocking.rs
@@ -3,19 +3,43 @@
 extern crate test;
 
 use bastion_executor::blocking;
-use bastion_executor::run::run;
-use futures::future::join_all;
 use lightproc::proc_stack::ProcStack;
-use lightproc::recoverable_handle::RecoverableHandle;
 use std::thread;
 use std::time::Duration;
 use test::Bencher;
 
+#[cfg(feature = "tokio-runtime")]
+mod tokio_benchs {
+    use super::*;
+    #[bench]
+    fn blocking(b: &mut Bencher) {
+        tokio_test::block_on(async { _blocking(b) });
+    }
+    #[bench]
+    fn blocking_single(b: &mut Bencher) {
+        tokio_test::block_on(async {
+            _blocking_single(b);
+        });
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod no_tokio_benchs {
+    use super::*;
+    #[bench]
+    fn blocking(b: &mut Bencher) {
+        _blocking(b);
+    }
+    #[bench]
+    fn blocking_single(b: &mut Bencher) {
+        _blocking_single(b);
+    }
+}
+
 // Benchmark for a 10K burst task spawn
-#[bench]
-fn blocking(b: &mut Bencher) {
+fn _blocking(b: &mut Bencher) {
     b.iter(|| {
-        let handles = (0..10_000)
+        (0..10_000)
             .map(|_| {
                 blocking::spawn_blocking(
                     async {
@@ -25,15 +49,12 @@ fn blocking(b: &mut Bencher) {
                     ProcStack::default(),
                 )
             })
-            .collect::<Vec<RecoverableHandle<()>>>();
-
-        run(join_all(handles), ProcStack::default());
+            .collect::<Vec<_>>()
     });
 }
 
 // Benchmark for a single blocking task spawn
-#[bench]
-fn blocking_single(b: &mut Bencher) {
+fn _blocking_single(b: &mut Bencher) {
     b.iter(|| {
         blocking::spawn_blocking(
             async {
diff --git a/src/bastion-executor/benches/run_blocking.rs b/src/bastion-executor/benches/run_blocking.rs
new file mode 100644
index 00000000..43de4400
--- /dev/null
+++ b/src/bastion-executor/benches/run_blocking.rs
@@ -0,0 +1,69 @@
+#![feature(test)]
+
+extern crate test;
+
+use bastion_executor::blocking;
+use bastion_executor::run::run;
+use futures::future::join_all;
+use lightproc::proc_stack::ProcStack;
+use std::thread;
+use std::time::Duration;
+use test::Bencher;
+
+#[cfg(feature = "tokio-runtime")]
+mod tokio_benchs {
+    use super::*;
+    #[bench]
+    fn blocking(b: &mut Bencher) {
+        tokio_test::block_on(async { _blocking(b) });
+    }
+    #[bench]
+    fn blocking_single(b: &mut Bencher) {
+        tokio_test::block_on(async {
+            _blocking_single(b);
+        });
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod no_tokio_benchs {
+    use super::*;
+    #[bench]
+    fn blocking(b: &mut Bencher) {
+        _blocking(b);
+    }
+    #[bench]
+    fn blocking_single(b: &mut Bencher) {
+        _blocking_single(b);
+    }
+}
+
+// Benchmark for a 10K burst task spawn
+fn _blocking(b: &mut Bencher) {
+    b.iter(|| {
+        (0..10_000)
+            .map(|_| {
+                blocking::spawn_blocking(
+                    async {
+                        let duration = Duration::from_millis(1);
+                        thread::sleep(duration);
+                    },
+                    ProcStack::default(),
+                )
+            })
+            .collect::<Vec<_>>()
+    });
+}
+
+// Benchmark for a single blocking task spawn
+fn _blocking_single(b: &mut Bencher) {
+    b.iter(|| {
+        blocking::spawn_blocking(
+            async {
+                let duration = Duration::from_millis(1);
+                thread::sleep(duration);
+            },
+            ProcStack::default(),
+        )
+    });
+}
diff --git a/src/bastion-executor/benches/spawn.rs b/src/bastion-executor/benches/spawn.rs
index f9d7d273..02b896bf 100644
--- a/src/bastion-executor/benches/spawn.rs
+++ b/src/bastion-executor/benches/spawn.rs
@@ -2,54 +2,69 @@
 
 extern crate test;
 
+use bastion_executor::load_balancer;
 use bastion_executor::prelude::spawn;
-use bastion_executor::run::run;
-use futures::future::join_all;
 use futures_timer::Delay;
 use lightproc::proc_stack::ProcStack;
-use lightproc::recoverable_handle::RecoverableHandle;
 use std::time::Duration;
 use test::Bencher;
 
+#[cfg(feature = "tokio-runtime")]
+mod tokio_benchs {
+    use super::*;
+    #[bench]
+    fn spawn_lot(b: &mut Bencher) {
+        tokio_test::block_on(async { _spawn_lot(b) });
+    }
+    #[bench]
+    fn spawn_single(b: &mut Bencher) {
+        tokio_test::block_on(async {
+            _spawn_single(b);
+        });
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod no_tokio_benchs {
+    use super::*;
+    #[bench]
+    fn spawn_lot(b: &mut Bencher) {
+        _spawn_lot(b);
+    }
+    #[bench]
+    fn spawn_single(b: &mut Bencher) {
+        _spawn_single(b);
+    }
+}
+
 // Benchmark for a 10K burst task spawn
-#[bench]
-fn spawn_lot(b: &mut Bencher) {
+fn _spawn_lot(b: &mut Bencher) {
+    let proc_stack = ProcStack::default();
     b.iter(|| {
-        let proc_stack = ProcStack::default();
-        let handles = (0..10_000)
+        let _ = (0..10_000)
             .map(|_| {
                 spawn(
                     async {
-                        let duration = Duration::from_millis(0);
+                        let duration = Duration::from_millis(1);
                         Delay::new(duration).await;
                     },
                     proc_stack.clone(),
                 )
             })
-            .collect::<Vec<RecoverableHandle<()>>>();
-
-        run(join_all(handles), proc_stack);
+            .collect::<Vec<_>>();
     });
 }
 
-// Benchmark for a single blocking task spawn
-#[bench]
-fn spawn_single(b: &mut Bencher) {
+// Benchmark for a single task spawn
+fn _spawn_single(b: &mut Bencher) {
+    let proc_stack = ProcStack::default();
     b.iter(|| {
-        let proc_stack = ProcStack::default();
-
-        let handle = spawn(
+        spawn(
             async {
-                let duration = Duration::from_millis(0);
+                let duration = Duration::from_millis(1);
                 Delay::new(duration).await;
             },
             proc_stack.clone(),
         );
-        run(
-            async {
-                handle.await;
-            },
-            proc_stack,
-        )
     });
 }
diff --git a/src/bastion-executor/benches/stats.rs b/src/bastion-executor/benches/stats.rs
index c6cb5f3f..684e7cb1 100644
--- a/src/bastion-executor/benches/stats.rs
+++ b/src/bastion-executor/benches/stats.rs
@@ -1,16 +1,16 @@
 #![feature(test)]
 
 extern crate test;
-use bastion_executor::load_balancer::{stats, SmpStats};
+use bastion_executor::load_balancer::{core_count, get_cores, stats, SmpStats};
 use bastion_executor::placement;
 use std::thread;
+use test::Bencher;
 
 fn stress_stats<S: SmpStats + Sync + Send>(stats: &'static S) {
-    let cores = placement::get_core_ids().expect("Core mapping couldn't be fetched");
-    let mut handles = Vec::new();
-    for core in cores {
+    let mut handles = Vec::with_capacity(*core_count());
+    for core in get_cores() {
         let handle = thread::spawn(move || {
-            placement::set_for_current(core);
+            placement::set_for_current(*core);
             for i in 0..100 {
                 stats.store_load(core.id, 10);
                 if i % 3 == 0 {
@@ -25,7 +25,6 @@ fn stress_stats<S: SmpStats + Sync + Send>(stats: &'static S) {
         handle.join().unwrap();
     }
 }
-use test::Bencher;
 
 // previous lock based stats benchmark 1,352,791 ns/iter (+/- 2,682,013)
 
@@ -36,3 +35,37 @@ fn lockless_stats_bench(b: &mut Bencher) {
         stress_stats(stats());
     });
 }
+
+#[bench]
+fn lockless_stats_bad_load(b: &mut Bencher) {
+    let stats = stats();
+    const MAX_CORE: usize = 256;
+    for i in 0..MAX_CORE {
+        // Generating the worst possible mergesort scenario
+        // [0,2,4,6,8,10,1,3,5,7,9]...
+        if i <= MAX_CORE / 2 {
+            stats.store_load(i, i * 2);
+        } else {
+            stats.store_load(i, i - 1 - MAX_CORE / 2);
+        }
+    }
+
+    b.iter(|| {
+        let _sorted_load = stats.get_sorted_load();
+    });
+}
+
+#[bench]
+fn lockless_stats_good_load(b: &mut Bencher) {
+    let stats = stats();
+    const MAX_CORE: usize = 256;
+    for i in 0..MAX_CORE {
+        // Generating the best possible mergesort scenario
+        // [0,1,2,3,4,5,6,7,8,9]...
+        stats.store_load(i, i);
+    }
+
+    b.iter(|| {
+        let _sorted_load = stats.get_sorted_load();
+    });
+}
diff --git a/src/bastion-executor/src/allocator.rs b/src/bastion-executor/src/allocator.rs
deleted file mode 100644
index 74d55955..00000000
--- a/src/bastion-executor/src/allocator.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//!
-//! NUMA-aware locality enabled allocator with optional fallback.
-//!
-//! Currently this API marked as `unstable` and can only be used with `unstable` feature.
-//!
-//! This allocator checks for NUMA-aware locality, and if it suitable it can start
-//! this allocator with local allocation policy [MPOL_LOCAL].
-//! In other cases otherwise it tries to use jemalloc.
-//!
-//! This allocator is an allocator called [Numanji].
-//!
-//! [Numanji]: https://docs.rs/numanji
-//! [MPOL_LOCAL]: http://man7.org/linux/man-pages/man2/set_mempolicy.2.html
-//!
-unstable_api! {
-    // Allocation selector import
-    use numanji::*;
-
-    // Drive selection of allocator here
-    autoselect!();
-}
diff --git a/src/bastion-executor/src/blocking.rs b/src/bastion-executor/src/blocking.rs
index 2fe269a5..5f595ebb 100644
--- a/src/bastion-executor/src/blocking.rs
+++ b/src/bastion-executor/src/blocking.rs
@@ -1,333 +1,151 @@
-//! A thread pool for running blocking functions asynchronously.
 //!
-//! Blocking thread pool consists of four elements:
-//! * Frequency Detector
-//! * Trend Estimator
-//! * Predictive Upscaler
-//! * Time-based Downscaler
+//! Pool of threads to run heavy processes
 //!
-//! ## Frequency Detector
-//! Detects how many tasks are submitted from scheduler to thread pool in a given time frame.
-//! Pool manager thread does this sampling every 200 milliseconds.
-//! This value is going to be used for trend estimation phase.
+//! We spawn futures onto the pool with [`spawn_blocking`] method of global run queue or
+//! with corresponding [`Worker`]'s spawn method.
 //!
-//! ## Trend Estimator
-//! Hold up to the given number of frequencies to create an estimation.
-//! Trend estimator holds 10 frequencies at a time.
-//! This value is stored as constant in [FREQUENCY_QUEUE_SIZE](constant.FREQUENCY_QUEUE_SIZE.html).
-//! Estimation algorithm and prediction uses Exponentially Weighted Moving Average algorithm.
-//!
-//! This algorithm is adapted from [A Novel Predictive and Self–Adaptive Dynamic Thread Pool Management](https://doi.org/10.1109/ISPA.2011.61)
-//! and altered to:
-//! * use instead of heavy calculation of trend, utilize thread redundancy which is the sum of the differences between the predicted and observed value.
-//! * use instead of linear trend estimation, it uses exponential trend estimation where formula is:
-//! ```text
-//! LOW_WATERMARK * (predicted - observed) + LOW_WATERMARK
-//! ```
-//! *NOTE:* If this algorithm wants to be tweaked increasing [LOW_WATERMARK](constant.LOW_WATERMARK.html) will automatically adapt the additional dynamic thread spawn count
-//! * operate without watermarking by timestamps (in paper which is used to measure algorithms own performance during the execution)
-//! * operate extensive subsampling. Extensive subsampling congests the pool manager thread.
-//! * operate without keeping track of idle time of threads or job out queue like TEMA and FOPS implementations.
-//!
-//! ## Predictive Upscaler
-//! Upscaler has three cases (also can be seen in paper):
-//! * The rate slightly increases and there are many idle threads.
-//! * The number of worker threads tends to be reduced since the workload of the system is descending.
-//! * The system has no request or stalled. (Our case here is when the current tasks block further tasks from being processed – throughput hogs)
-//!
-//! For the first two EMA calculation and exponential trend estimation gives good performance.
-//! For the last case, upscaler selects upscaling amount by amount of tasks mapped when throughput hogs happen.
-//!
-//! **example scenario:** Let's say we have 10_000 tasks where every one of them is blocking for 1 second. Scheduler will map plenty of tasks but will got rejected.
-//! This makes estimation calculation nearly 0 for both entering and exiting parts. When this happens and we still see tasks mapped from scheduler.
-//! We start to slowly increase threads by amount of frequency linearly. High increase of this value either make us hit to the thread threshold on
-//! some OS or make congestion on the other thread utilizations of the program, because of context switch.
-//!
-//! Throughput hogs determined by a combination of job in / job out frequency and current scheduler task assignment frequency.
-//! Threshold of EMA difference is eluded by machine epsilon for floating point arithmetic errors.
-//!
-//! ## Time-based Downscaler
-//! When threads becomes idle, they will not shut down immediately.
-//! Instead, they wait a random amount between 1 and 11 seconds
-//! to even out the load.
+//! [`Worker`]: crate::run_queue::Worker
 
-use std::collections::VecDeque;
-use std::future::Future;
-use std::io::ErrorKind;
-use std::iter::Iterator;
-use std::sync::atomic::{AtomicU64, Ordering};
-use std::sync::Mutex;
-use std::time::Duration;
-use std::{env, thread};
-
-use crossbeam_channel::{bounded, Receiver, Sender};
-
-use bastion_utils::math;
+use crate::thread_manager::{DynamicPoolManager, DynamicRunner};
+use crossbeam_channel::{unbounded, Receiver, Sender};
 use lazy_static::lazy_static;
 use lightproc::lightproc::LightProc;
 use lightproc::proc_stack::ProcStack;
 use lightproc::recoverable_handle::RecoverableHandle;
-
-use crate::placement::CoreId;
-use crate::{load_balancer, placement};
+use once_cell::sync::{Lazy, OnceCell};
+use std::future::Future;
+use std::iter::Iterator;
+use std::sync::Arc;
+use std::time::Duration;
+use std::{env, thread};
+use tracing::trace;
 
 /// If low watermark isn't configured this is the default scaler value.
 /// This value is used for the heuristics of the scaler
 const DEFAULT_LOW_WATERMARK: u64 = 2;
 
-/// Pool managers interval time (milliseconds).
-/// This is the actual interval which makes adaptation calculation.
-const MANAGER_POLL_INTERVAL: u64 = 200;
-
-/// Frequency histogram's sliding window size.
-/// Defines how many frequencies will be considered for adaptation.
-const FREQUENCY_QUEUE_SIZE: usize = 10;
-
-/// Exponential moving average smoothing coefficient for limited window.
-/// Smoothing factor is estimated with: 2 / (N + 1) where N is sample size.
-const EMA_COEFFICIENT: f64 = 2_f64 / (FREQUENCY_QUEUE_SIZE as f64 + 1_f64);
-
-/// Pool task frequency variable.
-/// Holds scheduled tasks onto the thread pool for the calculation time window.
-static FREQUENCY: AtomicU64 = AtomicU64::new(0);
-
-/// Possible max threads (without OS contract).
-static MAX_THREADS: AtomicU64 = AtomicU64::new(10_000);
-
-/// Pool interface between the scheduler and thread pool
-struct Pool {
-    sender: Sender<LightProc>,
-    receiver: Receiver<LightProc>,
-}
-
-lazy_static! {
-    /// Blocking pool with static starting thread count.
-    static ref POOL: Pool = {
-        for _ in 0..*low_watermark() {
-            thread::Builder::new()
-                .name("bastion-blocking-driver".to_string())
-                .spawn(|| {
-                    self::affinity_pinner();
-
-                    for task in &POOL.receiver {
-                        task.run();
-                    }
-                })
-                .expect("cannot start a thread driving blocking tasks");
-        }
-
-        // Pool manager to check frequency of task rates
-        // and take action by scaling the pool accordingly.
-        thread::Builder::new()
-            .name("bastion-pool-manager".to_string())
-            .spawn(|| {
-                let poll_interval = Duration::from_millis(MANAGER_POLL_INTERVAL);
-                loop {
-                    scale_pool();
-                    thread::sleep(poll_interval);
-                }
-            })
-            .expect("thread pool manager cannot be started");
-
-        // We want to use an unbuffered channel here to help
-        // us drive our dynamic control. In effect, the
-        // kernel's scheduler becomes the queue, reducing
-        // the number of buffers that work must flow through
-        // before being acted on by a core. This helps keep
-        // latency snappy in the overall async system by
-        // reducing bufferbloat.
-        let (sender, receiver) = bounded(0);
-        Pool { sender, receiver }
-    };
+const THREAD_RECV_TIMEOUT: Duration = Duration::from_millis(100);
 
-    static ref ROUND_ROBIN_PIN: Mutex<CoreId> = Mutex::new(CoreId { id: 0 });
-
-    /// Sliding window for pool task frequency calculation
-    static ref FREQ_QUEUE: Mutex<VecDeque<u64>> = {
-        Mutex::new(VecDeque::with_capacity(FREQUENCY_QUEUE_SIZE.saturating_add(1)))
-    };
-
-    /// Dynamic pool thread count variable
-    static ref POOL_SIZE: Mutex<u64> = Mutex::new(*low_watermark());
+/// Spawns a blocking task.
+///
+/// The task will be spawned onto a thread pool specifically dedicated to blocking tasks.
+pub fn spawn_blocking<F, R>(future: F, stack: ProcStack) -> RecoverableHandle<R>
+where
+    F: Future<Output = R> + Send + 'static,
+    R: Send + 'static,
+{
+    let (task, handle) = LightProc::recoverable(future, schedule, stack);
+    task.schedule();
+    handle
 }
 
-/// Exponentially Weighted Moving Average calculation
-///
-/// This allows us to find the EMA value.
-/// This value represents the trend of tasks mapped onto the thread pool.
-/// Calculation is following:
-/// ```text
-/// +--------+-----------------+----------------------------------+
-/// | Symbol |   Identifier    |           Explanation            |
-/// +--------+-----------------+----------------------------------+
-/// | α      | EMA_COEFFICIENT | smoothing factor between 0 and 1 |
-/// | Yt     | freq            | frequency sample at time t       |
-/// | St     | acc             | EMA at time t                    |
-/// +--------+-----------------+----------------------------------+
-/// ```
-/// Under these definitions formula is following:
-/// ```text
-/// EMA = α * [ Yt + (1 - α)*Yt-1 + ((1 - α)^2)*Yt-2 + ((1 - α)^3)*Yt-3 ... ] + St
-/// ```
-/// # Arguments
-///
-/// * `freq_queue` - Sliding window of frequency samples
-#[inline]
-fn calculate_ema(freq_queue: &VecDeque<u64>) -> f64 {
-    freq_queue.iter().enumerate().fold(0_f64, |acc, (i, freq)| {
-        acc + ((*freq as f64) * ((1_f64 - EMA_COEFFICIENT).powf(i as f64) as f64))
-    }) * EMA_COEFFICIENT as f64
+struct BlockingRunner {
+    // We keep a handle to the tokio runtime here to make sure
+    // it will never be dropped while the DynamicPoolManager is alive,
+    // In case we need to spin up some threads.
+    #[cfg(feature = "tokio-runtime")]
+    runtime_handle: tokio::runtime::Handle,
 }
 
-/// Adaptive pool scaling function
-///
-/// This allows to spawn new threads to make room for incoming task pressure.
-/// Works in the background detached from the pool system and scales up the pool based
-/// on the request rate.
-///
-/// It uses frequency based calculation to define work. Utilizing average processing rate.
-fn scale_pool() {
-    // Fetch current frequency, it does matter that operations are ordered in this approach.
-    let current_frequency = FREQUENCY.swap(0, Ordering::SeqCst);
-    let mut freq_queue = FREQ_QUEUE.lock().unwrap();
+impl DynamicRunner for BlockingRunner {
+    fn run_static(&self, park_timeout: Duration) -> ! {
+        loop {
+            while let Ok(task) = POOL.receiver.recv_timeout(THREAD_RECV_TIMEOUT) {
+                trace!("static thread: running task");
+                self.run(task);
+            }
 
-    // Make it safe to start for calculations by adding initial frequency scale
-    if freq_queue.len() == 0 {
-        freq_queue.push_back(0);
+            trace!("static: empty queue, parking with timeout");
+            thread::park_timeout(park_timeout);
+        }
     }
+    fn run_dynamic(&self, parker: &dyn Fn()) -> ! {
+        loop {
+            while let Ok(task) = POOL.receiver.recv_timeout(THREAD_RECV_TIMEOUT) {
+                trace!("dynamic thread: running task");
+                self.run(task);
+            }
+            trace!(
+                "dynamic thread: parking - {:?}",
+                std::thread::current().id()
+            );
+            parker();
+        }
+    }
+    fn run_standalone(&self) {
+        while let Ok(task) = POOL.receiver.recv_timeout(THREAD_RECV_TIMEOUT) {
+            self.run(task);
+        }
+        trace!("standalone thread: quitting.");
+    }
+}
 
-    // Calculate message rate for the given time window
-    let frequency = (current_frequency as f64 / MANAGER_POLL_INTERVAL as f64) as u64;
-
-    // Calculates current time window's EMA value (including last sample)
-    let prev_ema_frequency = calculate_ema(&freq_queue);
-
-    // Add seen frequency data to the frequency histogram.
-    freq_queue.push_back(frequency);
-    if freq_queue.len() == FREQUENCY_QUEUE_SIZE.saturating_add(1) {
-        freq_queue.pop_front();
+impl BlockingRunner {
+    fn run(&self, task: LightProc) {
+        #[cfg(feature = "tokio-runtime")]
+        {
+            self.runtime_handle.spawn_blocking(|| task.run());
+        }
+        #[cfg(not(feature = "tokio-runtime"))]
+        {
+            task.run();
+        }
     }
+}
 
-    // Calculates current time window's EMA value (including last sample)
-    let curr_ema_frequency = calculate_ema(&freq_queue);
+/// Pool interface between the scheduler and thread pool
+struct Pool {
+    sender: Sender<LightProc>,
+    receiver: Receiver<LightProc>,
+}
 
-    // Adapts the thread count of pool
-    //
-    // Sliding window of frequencies visited by the pool manager.
-    // Pool manager creates EMA value for previous window and current window.
-    // Compare them to determine scaling amount based on the trends.
-    // If current EMA value is bigger, we will scale up.
-    if curr_ema_frequency > prev_ema_frequency {
-        // "Scale by" amount can be seen as "how much load is coming".
-        // "Scale" amount is "how many threads we should spawn".
-        let scale_by: f64 = curr_ema_frequency - prev_ema_frequency;
-        let scale = num_cpus::get().min(
-            ((DEFAULT_LOW_WATERMARK as f64 * scale_by) + DEFAULT_LOW_WATERMARK as f64) as usize,
-        );
+static DYNAMIC_POOL_MANAGER: OnceCell<DynamicPoolManager> = OnceCell::new();
 
-        // It is time to scale the pool!
-        (0..scale).for_each(|_| {
-            create_blocking_thread();
-        });
-    } else if (curr_ema_frequency - prev_ema_frequency).abs() < std::f64::EPSILON
-        && current_frequency != 0
+static POOL: Lazy<Pool> = Lazy::new(|| {
+    #[cfg(feature = "tokio-runtime")]
     {
-        // Throughput is low. Allocate more threads to unblock flow.
-        // If we fall to this case, scheduler is congested by longhauling tasks.
-        // For unblock the flow we should add up some threads to the pool, but not that many to
-        // stagger the program's operation.
-        (0..DEFAULT_LOW_WATERMARK).for_each(|_| {
-            create_blocking_thread();
+        let runner = Arc::new(BlockingRunner {
+            // We use current() here instead of try_current()
+            // because we want bastion to crash as soon as possible
+            // if there is no available runtime.
+            runtime_handle: tokio::runtime::Handle::current(),
         });
-    }
-}
 
-/// Creates blocking thread to receive tasks
-/// Dynamic threads will terminate themselves if they don't
-/// receive any work after between one and ten seconds.
-fn create_blocking_thread() {
-    // Check that thread is spawnable.
-    // If it hits to the OS limits don't spawn it.
+        DYNAMIC_POOL_MANAGER
+            .set(DynamicPoolManager::new(*low_watermark() as usize, runner))
+            .expect("couldn't create dynamic pool manager");
+    }
+    #[cfg(not(feature = "tokio-runtime"))]
     {
-        let pool_size = *POOL_SIZE.lock().unwrap();
-        if pool_size >= MAX_THREADS.load(Ordering::SeqCst) {
-            MAX_THREADS.store(10_000, Ordering::SeqCst);
-            return;
-        }
+        let runner = Arc::new(BlockingRunner {});
+
+        DYNAMIC_POOL_MANAGER
+            .set(DynamicPoolManager::new(*low_watermark() as usize, runner))
+            .expect("couldn't create dynamic pool manager");
     }
-    // We want to avoid having all threads terminate at
-    // exactly the same time, causing thundering herd
-    // effects. We want to stagger their destruction over
-    // 10 seconds or so to make the costs fade into
-    // background noise.
-    //
-    // Generate a simple random number of milliseconds
-    let rand_sleep_ms = 1000_u64
-        .checked_add(u64::from(math::random(10_000)))
-        .expect("shouldn't overflow");
 
-    let _ = thread::Builder::new()
-        .name("bastion-blocking-driver-dynamic".to_string())
-        .spawn(move || {
-            self::affinity_pinner();
+    DYNAMIC_POOL_MANAGER
+        .get()
+        .expect("couldn't get static pool manager")
+        .initialize();
 
-            let wait_limit = Duration::from_millis(rand_sleep_ms);
-
-            // Adjust the pool size counter before and after spawn
-            *POOL_SIZE.lock().unwrap() += 1;
-            while let Ok(task) = POOL.receiver.recv_timeout(wait_limit) {
-                task.run();
-            }
-            *POOL_SIZE.lock().unwrap() -= 1;
-        })
-        .map_err(|err| {
-            match err.kind() {
-                ErrorKind::WouldBlock => {
-                    // Maximum allowed threads per process is varying from system to system.
-                    // Also, some systems have it(like macOS), and some don't(Linux).
-                    // This case expected not to happen.
-                    // But when happened this shouldn't throw a panic.
-                    let guarded_count = POOL_SIZE
-                        .lock()
-                        .unwrap()
-                        .checked_sub(1)
-                        .expect("shouldn't underflow");
-                    MAX_THREADS.store(guarded_count, Ordering::SeqCst);
-                }
-                _ => eprintln!(
-                    "cannot start a dynamic thread driving blocking tasks: {}",
-                    err
-                ),
-            }
-        });
-}
+    let (sender, receiver) = unbounded();
+    Pool { sender, receiver }
+});
 
 /// Enqueues work, attempting to send to the thread pool in a
 /// nonblocking way and spinning up needed amount of threads
 /// based on the previous statistics without relying on
 /// if there is not a thread ready to accept the work or not.
 fn schedule(t: LightProc) {
-    // Add up for every incoming scheduled task
-    FREQUENCY.fetch_add(1, Ordering::Acquire);
-
     if let Err(err) = POOL.sender.try_send(t) {
         // We were not able to send to the channel without
         // blocking.
         POOL.sender.send(err.into_inner()).unwrap();
     }
-}
 
-/// Spawns a blocking task.
-///
-/// The task will be spawned onto a thread pool specifically dedicated to blocking tasks.
-pub fn spawn_blocking<F, R>(future: F, stack: ProcStack) -> RecoverableHandle<R>
-where
-    F: Future<Output = R> + Send + 'static,
-    R: Send + 'static,
-{
-    let (task, handle) = LightProc::recoverable(future, schedule, stack);
-    task.schedule();
-    handle
+    // Add up for every incoming scheduled task
+    DYNAMIC_POOL_MANAGER.get().unwrap().increment_frequency();
 }
 
 ///
@@ -335,7 +153,7 @@ where
 /// Spawns initial thread set.
 /// Can be configurable with env var `BASTION_BLOCKING_THREADS` at runtime.
 #[inline]
-pub fn low_watermark() -> &'static u64 {
+fn low_watermark() -> &'static u64 {
     lazy_static! {
         static ref LOW_WATERMARK: u64 = {
             env::var_os("BASTION_BLOCKING_THREADS")
@@ -346,15 +164,3 @@ pub fn low_watermark() -> &'static u64 {
 
     &*LOW_WATERMARK
 }
-
-///
-/// Affinity pinner for blocking pool
-/// Pinning isn't going to be enabled for single core systems.
-#[inline]
-pub fn affinity_pinner() {
-    if 1 != *load_balancer::core_retrieval() {
-        let mut core = ROUND_ROBIN_PIN.lock().unwrap();
-        placement::set_for_current(*core);
-        core.id = (core.id + 1) % *load_balancer::core_retrieval();
-    }
-}
diff --git a/src/bastion-executor/src/distributor.rs b/src/bastion-executor/src/distributor.rs
deleted file mode 100644
index 13548304..00000000
--- a/src/bastion-executor/src/distributor.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-//!
-//! Cache affine thread pool distributor
-//!
-//! Distributor provides a fair distribution of threads and pinning them to cores for fair execution.
-//! It assigns threads in round-robin fashion to all cores.
-use crate::placement::{self, CoreId};
-use crate::run_queue::{Stealer, Worker};
-use crate::worker;
-use lightproc::prelude::*;
-use std::thread;
-
-pub(crate) struct Distributor {
-    pub(crate) cores: Vec<CoreId>,
-}
-
-impl Distributor {
-    pub(crate) fn new() -> Self {
-        Distributor {
-            cores: placement::get_core_ids().expect("Core mapping couldn't be fetched"),
-        }
-    }
-
-    pub(crate) fn assign(self) -> Vec<Stealer<LightProc>> {
-        let mut stealers = Vec::<Stealer<LightProc>>::new();
-
-        for core in self.cores {
-            let wrk = Worker::new_fifo();
-            stealers.push(wrk.stealer());
-
-            thread::Builder::new()
-                .name("bastion-async-thread".to_string())
-                .spawn(move || {
-                    // affinity assignment
-                    placement::set_for_current(core);
-
-                    // run initial stats generation for cores
-                    worker::stats_generator(core.id, &wrk);
-                    // actual execution
-                    worker::main_loop(core.id, wrk);
-                })
-                .expect("cannot start the thread for running proc");
-        }
-
-        stealers
-    }
-}
diff --git a/src/bastion-executor/src/lib.rs b/src/bastion-executor/src/lib.rs
index aa885077..145614c2 100644
--- a/src/bastion-executor/src/lib.rs
+++ b/src/bastion-executor/src/lib.rs
@@ -28,26 +28,15 @@
 // Force missing implementations
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
-#![cfg_attr(
-    any(feature = "numanji", feature = "allocator-suite"),
-    feature(allocator_api)
-)]
-#![cfg_attr(
-    any(feature = "numanji", feature = "allocator-suite"),
-    feature(nonnull_slice_from_raw_parts)
-)]
-#[macro_use]
-mod macros;
 
-pub mod allocator;
 pub mod blocking;
-pub mod distributor;
 pub mod load_balancer;
 pub mod placement;
 pub mod pool;
 pub mod run;
 pub mod run_queue;
 pub mod sleepers;
+mod thread_manager;
 pub mod worker;
 
 ///
diff --git a/src/bastion-executor/src/load_balancer.rs b/src/bastion-executor/src/load_balancer.rs
index 2ee4a1c8..9b253f6c 100644
--- a/src/bastion-executor/src/load_balancer.rs
+++ b/src/bastion-executor/src/load_balancer.rs
@@ -7,49 +7,102 @@
 use crate::load_balancer;
 use crate::placement;
 use arrayvec::ArrayVec;
+use fmt::{Debug, Formatter};
 use lazy_static::*;
+use once_cell::sync::Lazy;
+use placement::CoreId;
 use std::mem::MaybeUninit;
-use std::sync::atomic::{AtomicUsize, Ordering};
-use std::thread;
-use std::time::Duration;
+use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+use std::sync::RwLock;
+use std::time::{Duration, Instant};
 use std::{fmt, usize};
+use tracing::{debug, error};
+
+const MEAN_UPDATE_TRESHOLD: Duration = Duration::from_millis(200);
 
 /// Stats of all the smp queues.
 pub trait SmpStats {
     /// Stores the load of the given queue.
     fn store_load(&self, affinity: usize, load: usize);
-    /// returns tuple of queue id and load in an sorted order.
-    fn get_sorted_load(&self) -> ArrayVec<[(usize, usize); MAX_CORE]>;
+    /// returns tuple of queue id and load ordered from highest load to lowest.
+    fn get_sorted_load(&self) -> ArrayVec<(usize, usize), MAX_CORE>;
     /// mean of the all smp queue load.
     fn mean(&self) -> usize;
     /// update the smp mean.
     fn update_mean(&self);
 }
-///
-/// Load-balancer struct which is just a convenience wrapper over the statistics calculations.
-#[derive(Debug)]
-pub struct LoadBalancer;
+
+static LOAD_BALANCER: Lazy<LoadBalancer> = Lazy::new(|| {
+    let lb = LoadBalancer::new(placement::get_core_ids().unwrap());
+    debug!("Instantiated load_balancer: {:?}", lb);
+    lb
+});
+
+/// Load-balancer struct which allows us to update the mean load
+pub struct LoadBalancer {
+    /// The number of cores
+    /// available for this program
+    pub num_cores: usize,
+    /// The core Ids available for this program
+    /// This doesn't take affinity into account
+    pub cores: Vec<CoreId>,
+    mean_last_updated_at: RwLock<Instant>,
+}
 
 impl LoadBalancer {
-    ///
-    /// AMQL sampling thread for run queue load balancing.
-    pub fn amql_generation() {
-        thread::Builder::new()
-            .name("bastion-load-balancer-thread".to_string())
-            .spawn(move || {
-                loop {
-                    load_balancer::stats().update_mean();
-                    // We don't have β-reduction here… Life is unfair. Life is cruel.
-                    //
-                    // Try sleeping for a while to wait
-                    // Should be smaller time slice than 4 times per second to not miss
-                    thread::sleep(Duration::from_millis(245));
-                    // Yield immediately back to os so we can advance in workers
-                    thread::yield_now();
-                }
+    /// Creates a new LoadBalancer.
+    /// if you're looking for `num_cores` and `cores`
+    /// Have a look at `load_balancer::core_count()`
+    /// and `load_balancer::get_cores()` respectively.
+    pub fn new(cores: Vec<CoreId>) -> Self {
+        Self {
+            num_cores: cores.len(),
+            cores,
+            mean_last_updated_at: RwLock::new(Instant::now()),
+        }
+    }
+}
+
+impl Debug for LoadBalancer {
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        fmt.debug_struct("LoadBalancer")
+            .field("num_cores", &self.num_cores)
+            .field("cores", &self.cores)
+            .field("mean_last_updated_at", &self.mean_last_updated_at)
+            .finish()
+    }
+}
+
+impl LoadBalancer {
+    /// Iterates the statistics to get the mean load across the cores
+    pub fn update_load_mean(&self) {
+        // Check if update should occur
+        if !self.should_update() {
+            return;
+        }
+        self.mean_last_updated_at
+            .write()
+            .map(|mut last_updated_at| {
+                *last_updated_at = Instant::now();
             })
-            .expect("load-balancer couldn't start");
+            .unwrap_or_else(|e| error!("couldn't update mean timestamp - {}", e));
+
+        load_balancer::stats().update_mean();
     }
+
+    fn should_update(&self) -> bool {
+        // If we couldn't acquire a lock on the mean last_updated_at,
+        // There is probably someone else updating already
+        self.mean_last_updated_at
+            .try_read()
+            .map(|last_updated_at| last_updated_at.elapsed() > MEAN_UPDATE_TRESHOLD)
+            .unwrap_or(false)
+    }
+}
+
+/// Update the mean load on the singleton
+pub fn update() {
+    LOAD_BALANCER.update_load_mean()
 }
 
 /// Maximum number of core supported by modern computers.
@@ -64,6 +117,7 @@ const MAX_CORE: usize = 256;
 pub struct Stats {
     smp_load: [AtomicUsize; MAX_CORE],
     mean_level: AtomicUsize,
+    updating_mean: AtomicBool,
 }
 
 impl fmt::Debug for Stats {
@@ -71,6 +125,7 @@ impl fmt::Debug for Stats {
         fmt.debug_struct("Stats")
             .field("smp_load", &&self.smp_load[..])
             .field("mean_level", &self.mean_level)
+            .field("updating_mean", &self.updating_mean)
             .finish()
     }
 }
@@ -81,26 +136,24 @@ impl Stats {
         let smp_load: [AtomicUsize; MAX_CORE] = {
             let mut data: [MaybeUninit<AtomicUsize>; MAX_CORE] =
                 unsafe { MaybeUninit::uninit().assume_init() };
-            let mut i = 0;
-            while i < MAX_CORE {
-                if i < num_cores {
-                    unsafe {
-                        std::ptr::write(data[i].as_mut_ptr(), AtomicUsize::new(0));
-                    }
-                    i += 1;
-                    continue;
+
+            for core_data in data.iter_mut().take(num_cores) {
+                unsafe {
+                    std::ptr::write(core_data.as_mut_ptr(), AtomicUsize::new(0));
                 }
-                // MAX is for unused slot.
+            }
+            for core_data in data.iter_mut().take(MAX_CORE).skip(num_cores) {
                 unsafe {
-                    std::ptr::write(data[i].as_mut_ptr(), AtomicUsize::new(usize::MAX));
+                    std::ptr::write(core_data.as_mut_ptr(), AtomicUsize::new(usize::MAX));
                 }
-                i += 1;
             }
+
             unsafe { std::mem::transmute::<_, [AtomicUsize; MAX_CORE]>(data) }
         };
         Stats {
             smp_load,
             mean_level: AtomicUsize::new(0),
+            updating_mean: AtomicBool::new(false),
         }
     }
 }
@@ -113,41 +166,46 @@ impl SmpStats for Stats {
         self.smp_load[affinity].store(load, Ordering::SeqCst);
     }
 
-    fn get_sorted_load(&self) -> ArrayVec<[(usize, usize); MAX_CORE]> {
-        let mut sorted_load = ArrayVec::<[(usize, usize); MAX_CORE]>::new();
+    fn get_sorted_load(&self) -> ArrayVec<(usize, usize), MAX_CORE> {
+        let mut sorted_load = ArrayVec::new();
 
-        for (i, item) in self.smp_load.iter().enumerate() {
-            let load = item.load(Ordering::SeqCst);
+        for (core, load) in self.smp_load.iter().enumerate() {
+            let load = load.load(Ordering::SeqCst);
             // load till maximum core.
             if load == usize::MAX {
                 break;
             }
             // unsafe is ok here because self.smp_load.len() is MAX_CORE
-            unsafe { sorted_load.push_unchecked((i, load)) };
+            unsafe { sorted_load.push_unchecked((core, load)) };
         }
         sorted_load.sort_by(|x, y| y.1.cmp(&x.1));
         sorted_load
     }
 
     fn mean(&self) -> usize {
-        self.mean_level.load(Ordering::SeqCst)
+        self.mean_level.load(Ordering::Acquire)
     }
 
     fn update_mean(&self) {
+        // Don't update if it's updating already
+        if self.updating_mean.load(Ordering::Acquire) {
+            return;
+        }
+
+        self.updating_mean.store(true, Ordering::Release);
         let mut sum: usize = 0;
+        let num_cores = LOAD_BALANCER.num_cores;
 
-        for item in self.smp_load.iter() {
-            let load = item.load(Ordering::SeqCst);
-            if let Some(tmp) = sum.checked_add(load) {
+        for item in self.smp_load.iter().take(num_cores) {
+            if let Some(tmp) = sum.checked_add(item.load(Ordering::Acquire)) {
                 sum = tmp;
-                continue;
             }
-            break;
         }
-        self.mean_level.store(
-            sum.wrapping_div(placement::get_core_ids().unwrap().len()),
-            Ordering::SeqCst,
-        );
+
+        self.mean_level
+            .store(sum.wrapping_div(num_cores), Ordering::Release);
+
+        self.updating_mean.store(false, Ordering::Release);
     }
 }
 
@@ -156,7 +214,7 @@ impl SmpStats for Stats {
 #[inline]
 pub fn stats() -> &'static Stats {
     lazy_static! {
-        static ref LOCKLESS_STATS: Stats = Stats::new(*core_retrieval());
+        static ref LOCKLESS_STATS: Stats = Stats::new(*core_count());
     }
     &*LOCKLESS_STATS
 }
@@ -164,10 +222,13 @@ pub fn stats() -> &'static Stats {
 ///
 /// Retrieve core count for the runtime scheduling purposes
 #[inline]
-pub fn core_retrieval() -> &'static usize {
-    lazy_static! {
-        static ref CORE_COUNT: usize = placement::get_core_ids().unwrap().len();
-    }
+pub fn core_count() -> &'static usize {
+    &LOAD_BALANCER.num_cores
+}
 
-    &*CORE_COUNT
+///
+/// Retrieve cores for the runtime scheduling purposes
+#[inline]
+pub fn get_cores() -> &'static [CoreId] {
+    &*LOAD_BALANCER.cores
 }
diff --git a/src/bastion-executor/src/macros.rs b/src/bastion-executor/src/macros.rs
deleted file mode 100644
index 56407401..00000000
--- a/src/bastion-executor/src/macros.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-///
-/// Marker of unstable API.
-#[doc(hidden)]
-macro_rules! unstable_api {
-    ($($block:item)*) => {
-        $(
-            #[cfg(feature = "unstable")]
-            $block
-        )*
-    }
-}
diff --git a/src/bastion-executor/src/placement.rs b/src/bastion-executor/src/placement.rs
index 27a368c3..1d3e0a76 100644
--- a/src/bastion-executor/src/placement.rs
+++ b/src/bastion-executor/src/placement.rs
@@ -10,9 +10,15 @@ pub fn get_core_ids() -> Option<Vec<CoreId>> {
     get_core_ids_helper()
 }
 
+/// This function tries to retrieve
+/// the number of active "cores" on the system.
+pub fn get_num_cores() -> Option<usize> {
+    get_core_ids().map(|ids| ids.len())
+}
 ///
 /// Sets the current threads affinity
 pub fn set_for_current(core_id: CoreId) {
+    tracing::trace!("Executor: placement: set affinity on core {}", core_id.id);
     set_for_current_helper(core_id);
 }
 
diff --git a/src/bastion-executor/src/pool.rs b/src/bastion-executor/src/pool.rs
index b8c919a9..191e0bb8 100644
--- a/src/bastion-executor/src/pool.rs
+++ b/src/bastion-executor/src/pool.rs
@@ -1,16 +1,26 @@
 //!
 //! Pool of threads to run lightweight processes
 //!
-//! Pool management and tracking belongs here.
-//! We spawn futures onto the pool with [spawn] method of global run queue or
-//! with corresponding [Worker]'s spawn method.
-use crate::distributor::Distributor;
-use crate::run_queue::{Injector, Stealer};
-use crate::sleepers::Sleepers;
+//! We spawn futures onto the pool with [`spawn`] method of global run queue or
+//! with corresponding [`Worker`]'s spawn method.
+//!
+//! [`spawn`]: crate::pool::spawn
+//! [`Worker`]: crate::run_queue::Worker
+
+use crate::thread_manager::{DynamicPoolManager, DynamicRunner};
 use crate::worker;
+use crossbeam_channel::{unbounded, Receiver, Sender};
 use lazy_static::lazy_static;
-use lightproc::prelude::*;
+use lightproc::lightproc::LightProc;
+use lightproc::proc_stack::ProcStack;
+use lightproc::recoverable_handle::RecoverableHandle;
+use once_cell::sync::{Lazy, OnceCell};
 use std::future::Future;
+use std::iter::Iterator;
+use std::sync::Arc;
+use std::time::Duration;
+use std::{env, thread};
+use tracing::trace;
 
 ///
 /// Spawn a process (which contains future + process stack) onto the executor from the global level.
@@ -20,6 +30,18 @@ use std::future::Future;
 /// use bastion_executor::prelude::*;
 /// use lightproc::prelude::*;
 ///
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    start();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    start();    
+/// # }
+/// #
+/// # fn start() {
 /// let pid = 1;
 /// let stack = ProcStack::default().with_pid(pid);
 ///
@@ -36,28 +58,36 @@ use std::future::Future;
 ///     },
 ///     stack.clone(),
 /// );
+/// # }
 /// ```
 pub fn spawn<F, T>(future: F, stack: ProcStack) -> RecoverableHandle<T>
 where
     F: Future<Output = T> + Send + 'static,
     T: Send + 'static,
 {
-    self::get().spawn(future, stack)
+    let (task, handle) = LightProc::recoverable(future, worker::schedule, stack);
+    task.schedule();
+    handle
 }
 
+/// Spawns a blocking task.
 ///
-/// Pool that global run queue, stealers of the workers, and parked threads.
-#[derive(Debug)]
-pub struct Pool {
-    ///
-    /// Global run queue implementation
-    pub(crate) injector: Injector<LightProc>,
-    ///
-    /// Stealers of the workers
-    pub(crate) stealers: Vec<Stealer<LightProc>>,
-    ///
-    /// Container of parked threads
-    pub(crate) sleepers: Sleepers,
+/// The task will be spawned onto a thread pool specifically dedicated to blocking tasks.
+pub fn spawn_blocking<F, R>(future: F, stack: ProcStack) -> RecoverableHandle<R>
+where
+    F: Future<Output = R> + Send + 'static,
+    R: Send + 'static,
+{
+    let (task, handle) = LightProc::recoverable(future, schedule, stack);
+    task.schedule();
+    handle
+}
+
+///
+/// Acquire the static Pool reference
+#[inline]
+pub fn get() -> &'static Pool {
+    &*POOL
 }
 
 impl Pool {
@@ -78,21 +108,132 @@ impl Pool {
     }
 }
 
+/// Enqueues work, attempting to send to the thread pool in a
+/// nonblocking way and spinning up needed amount of threads
+/// based on the previous statistics without relying on
+/// if there is not a thread ready to accept the work or not.
+pub(crate) fn schedule(t: LightProc) {
+    if let Err(err) = POOL.sender.try_send(t) {
+        // We were not able to send to the channel without
+        // blocking.
+        POOL.sender.send(err.into_inner()).unwrap();
+    }
+    // Add up for every incoming scheduled task
+    DYNAMIC_POOL_MANAGER.get().unwrap().increment_frequency();
+}
+
 ///
-/// Acquire the static Pool reference
+/// Low watermark value, defines the bare minimum of the pool.
+/// Spawns initial thread set.
+/// Can be configurable with env var `BASTION_BLOCKING_THREADS` at runtime.
 #[inline]
-pub fn get() -> &'static Pool {
+fn low_watermark() -> &'static u64 {
     lazy_static! {
-        static ref POOL: Pool = {
-            let distributor = Distributor::new();
-            let stealers = distributor.assign();
-
-            Pool {
-                injector: Injector::new(),
-                stealers,
-                sleepers: Sleepers::new(),
-            }
+        static ref LOW_WATERMARK: u64 = {
+            env::var_os("BASTION_BLOCKING_THREADS")
+                .map(|x| x.to_str().unwrap().parse::<u64>().unwrap())
+                .unwrap_or(DEFAULT_LOW_WATERMARK)
         };
     }
-    &*POOL
+
+    &*LOW_WATERMARK
+}
+
+/// If low watermark isn't configured this is the default scaler value.
+/// This value is used for the heuristics of the scaler
+const DEFAULT_LOW_WATERMARK: u64 = 2;
+
+/// Pool interface between the scheduler and thread pool
+#[derive(Debug)]
+pub struct Pool {
+    sender: Sender<LightProc>,
+    receiver: Receiver<LightProc>,
+}
+
+struct AsyncRunner {
+    // We keep a handle to the tokio runtime here to make sure
+    // it will never be dropped while the DynamicPoolManager is alive,
+    // In case we need to spin up some threads.
+    #[cfg(feature = "tokio-runtime")]
+    runtime_handle: tokio::runtime::Handle,
+}
+
+impl DynamicRunner for AsyncRunner {
+    fn run_static(&self, park_timeout: Duration) -> ! {
+        loop {
+            for task in &POOL.receiver {
+                trace!("static: running task");
+                self.run(task);
+            }
+
+            trace!("static: empty queue, parking with timeout");
+            thread::park_timeout(park_timeout);
+        }
+    }
+    fn run_dynamic(&self, parker: &dyn Fn()) -> ! {
+        loop {
+            while let Ok(task) = POOL.receiver.try_recv() {
+                trace!("dynamic thread: running task");
+                self.run(task);
+            }
+            trace!(
+                "dynamic thread: parking - {:?}",
+                std::thread::current().id()
+            );
+            parker();
+        }
+    }
+    fn run_standalone(&self) {
+        while let Ok(task) = POOL.receiver.try_recv() {
+            self.run(task);
+        }
+        trace!("standalone thread: quitting.");
+    }
 }
+
+impl AsyncRunner {
+    fn run(&self, task: LightProc) {
+        #[cfg(feature = "tokio-runtime")]
+        {
+            self.runtime_handle.spawn_blocking(|| task.run());
+        }
+        #[cfg(not(feature = "tokio-runtime"))]
+        {
+            task.run();
+        }
+    }
+}
+
+static DYNAMIC_POOL_MANAGER: OnceCell<DynamicPoolManager> = OnceCell::new();
+
+static POOL: Lazy<Pool> = Lazy::new(|| {
+    #[cfg(feature = "tokio-runtime")]
+    {
+        let runner = Arc::new(AsyncRunner {
+            // We use current() here instead of try_current()
+            // because we want bastion to crash as soon as possible
+            // if there is no available runtime.
+            runtime_handle: tokio::runtime::Handle::current(),
+        });
+
+        DYNAMIC_POOL_MANAGER
+            .set(DynamicPoolManager::new(*low_watermark() as usize, runner))
+            .expect("couldn't create dynamic pool manager");
+    }
+    #[cfg(not(feature = "tokio-runtime"))]
+    {
+        let runner = Arc::new(AsyncRunner {});
+
+        DYNAMIC_POOL_MANAGER
+            .set(DynamicPoolManager::new(*low_watermark() as usize, runner))
+            .expect("couldn't create dynamic pool manager");
+    }
+
+    DYNAMIC_POOL_MANAGER
+        .get()
+        .expect("couldn't get static pool manager")
+        .initialize();
+
+    let (sender, receiver) = unbounded();
+    Pool { sender, receiver }
+});
diff --git a/src/bastion-executor/src/run.rs b/src/bastion-executor/src/run.rs
index 4a3d5757..9eb62f64 100644
--- a/src/bastion-executor/src/run.rs
+++ b/src/bastion-executor/src/run.rs
@@ -7,11 +7,11 @@ use crossbeam_utils::sync::Parker;
 use lightproc::proc_stack::ProcStack;
 use std::cell::{Cell, UnsafeCell};
 use std::future::Future;
+use std::mem;
 use std::mem::ManuallyDrop;
 use std::pin::Pin;
 use std::sync::Arc;
 use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
-use std::{mem, panic};
 
 ///
 /// This method blocks the current thread until passed future is resolved with an output (including the panic).
diff --git a/src/bastion-executor/src/run_queue.rs b/src/bastion-executor/src/run_queue.rs
index a494ad11..ae196c17 100644
--- a/src/bastion-executor/src/run_queue.rs
+++ b/src/bastion-executor/src/run_queue.rs
@@ -18,39 +18,34 @@
 //!
 //! [`Worker`] has two constructors:
 //!
-//! * [`new_fifo()`] - Creates a FIFO queue, in which tasks are pushed and popped from opposite
+//! * [`new_fifo`] - Creates a FIFO queue, in which tasks are pushed and popped from opposite
 //!   ends.
-//! * [`new_lifo()`] - Creates a LIFO queue, in which tasks are pushed and popped from the same
+//! * [`new_lifo`] - Creates a LIFO queue, in which tasks are pushed and popped from the same
 //!   end.
 //!
 //! Each [`Worker`] is owned by a single thread and supports only push and pop operations.
 //!
-//! Method [`stealer()`] creates a [`Stealer`] that may be shared among threads and can only steal
+//! Method [`stealer`] creates a [`Stealer`] that may be shared among threads and can only steal
 //! tasks from its [`Worker`]. Tasks are stolen from the end opposite to where they get pushed.
 //!
 //! # Stealing
 //!
 //! Steal operations come in three flavors:
 //!
-//! 1. [`steal()`] - Steals one task.
-//! 2. [`steal_batch()`] - Steals a batch of tasks and moves them into another worker.
-//! 3. [`steal_batch_and_pop()`] - Steals a batch of tasks, moves them into another queue, and pops
+//! 1. [`steal`] - Steals one task.
+//! 2. [`steal_batch`] - Steals a batch of tasks and moves them into another worker.
+//! 3. [`steal_batch_and_pop`] - Steals a batch of tasks, moves them into another queue, and pops
 //!    one task from that worker.
 //!
 //! In contrast to push and pop operations, stealing can spuriously fail with [`Steal::Retry`], in
 //! which case the steal operation needs to be retried.
 //!
-//!
-//! [`Worker`]: struct.Worker.html
-//! [`Stealer`]: struct.Stealer.html
-//! [`Injector`]: struct.Injector.html
-//! [`Steal::Retry`]: enum.Steal.html#variant.Retry
-//! [`new_fifo()`]: struct.Worker.html#method.new_fifo
-//! [`new_lifo()`]: struct.Worker.html#method.new_lifo
-//! [`stealer()`]: struct.Worker.html#method.stealer
-//! [`steal()`]: struct.Stealer.html#method.steal
-//! [`steal_batch()`]: struct.Stealer.html#method.steal_batch
-//! [`steal_batch_and_pop()`]: struct.Stealer.html#method.steal_batch_and_pop
+//! [`new_fifo`]: Worker::new_fifo
+//! [`new_lifo`]: Worker::new_lifo
+//! [`stealer`]: Worker::stealer
+//! [`steal`]: Stealer::steal
+//! [`steal_batch`]: Stealer::steal_batch
+//! [`steal_batch_and_pop`]: Stealer::steal_batch_and_pop
 use crossbeam_epoch::{self as epoch, Atomic, Owned};
 use crossbeam_utils::{Backoff, CachePadded};
 use std::cell::{Cell, UnsafeCell};
@@ -1727,26 +1722,17 @@ pub enum Steal<T> {
 impl<T> Steal<T> {
     /// Returns `true` if the queue was empty at the time of stealing.
     pub fn is_empty(&self) -> bool {
-        match self {
-            Steal::Empty => true,
-            _ => false,
-        }
+        matches!(self, Steal::Empty)
     }
 
     /// Returns `true` if at least one task was stolen.
     pub fn is_success(&self) -> bool {
-        match self {
-            Steal::Success(_) => true,
-            _ => false,
-        }
+        matches!(self, Steal::Success(_))
     }
 
     /// Returns `true` if the steal operation needs to be retried.
     pub fn is_retry(&self) -> bool {
-        match self {
-            Steal::Retry => true,
-            _ => false,
-        }
+        matches!(self, Steal::Retry)
     }
 
     /// Returns the result of the operation, if successful.
@@ -1793,10 +1779,14 @@ impl<T> fmt::Debug for Steal<T> {
 }
 
 impl<T> FromIterator<Steal<T>> for Steal<T> {
-    /// Consumes items until a `Success` is found and returns it.
+    /// Consumes items until a [`Success`] is found and returns it.
+    ///
+    /// If no [`Success`] was found, but there was at least one [`Retry`], then returns [`Retry`].
+    /// Otherwise, [`Empty`] is returned.
     ///
-    /// If no `Success` was found, but there was at least one `Retry`, then returns `Retry`.
-    /// Otherwise, `Empty` is returned.
+    /// [`Success`]: Steal::Success
+    /// [`Retry`]: Steal::Retry
+    /// [`Empty`]: Steal::Empty
     fn from_iter<I>(iter: I) -> Steal<T>
     where
         I: IntoIterator<Item = Steal<T>>,
diff --git a/src/bastion-executor/src/thread_manager.rs b/src/bastion-executor/src/thread_manager.rs
new file mode 100644
index 00000000..4f89dc08
--- /dev/null
+++ b/src/bastion-executor/src/thread_manager.rs
@@ -0,0 +1,394 @@
+//! A thread manager to predict how many threads should be spawned to handle the upcoming load.
+//!
+//! The thread manager consists of three elements:
+//! * Frequency Detector
+//! * Trend Estimator
+//! * Predictive Upscaler
+//!
+//! ## Frequency Detector
+//! Detects how many tasks are submitted from scheduler to thread pool in a given time frame.
+//! Pool manager thread does this sampling every 90 milliseconds.
+//! This value is going to be used for trend estimation phase.
+//!
+//! ## Trend Estimator
+//! Hold up to the given number of frequencies to create an estimation.
+//! Trend estimator holds 10 frequencies at a time.
+//! This value is stored as constant in [FREQUENCY_QUEUE_SIZE](constant.FREQUENCY_QUEUE_SIZE.html).
+//! Estimation algorithm and prediction uses Exponentially Weighted Moving Average algorithm.
+//!
+//! This algorithm is adapted from [A Novel Predictive and Self–Adaptive Dynamic Thread Pool Management](https://doi.org/10.1109/ISPA.2011.61)
+//! and altered to:
+//! * use instead of heavy calculation of trend, utilize thread redundancy which is the sum of the differences between the predicted and observed value.
+//! * use instead of linear trend estimation, it uses exponential trend estimation where formula is:
+//! ```text
+//! LOW_WATERMARK * (predicted - observed) + LOW_WATERMARK
+//! ```
+//! *NOTE:* If this algorithm wants to be tweaked increasing [LOW_WATERMARK](constant.LOW_WATERMARK.html) will automatically adapt the additional dynamic thread spawn count
+//! * operate without watermarking by timestamps (in paper which is used to measure algorithms own performance during the execution)
+//! * operate extensive subsampling. Extensive subsampling congests the pool manager thread.
+//! * operate without keeping track of idle time of threads or job out queue like TEMA and FOPS implementations.
+//!
+//! ## Predictive Upscaler
+//! Upscaler has three cases (also can be seen in paper):
+//! * The rate slightly increases and there are many idle threads.
+//! * The number of worker threads tends to be reduced since the workload of the system is descending.
+//! * The system has no request or stalled. (Our case here is when the current tasks block further tasks from being processed – throughput hogs)
+//!
+//! For the first two EMA calculation and exponential trend estimation gives good performance.
+//! For the last case, upscaler selects upscaling amount by amount of tasks mapped when throughput hogs happen.
+//!
+//! **example scenario:** Let's say we have 10_000 tasks where every one of them is blocking for 1 second. Scheduler will map plenty of tasks but will get rejected.
+//! This makes estimation calculation nearly 0 for both entering and exiting parts. When this happens and we still see tasks mapped from scheduler.
+//! We start to slowly increase threads by amount of frequency linearly. High increase of this value either make us hit to the thread threshold on
+//! some OS or make congestion on the other thread utilizations of the program, because of context switch.
+//!
+//! Throughput hogs determined by a combination of job in / job out frequency and current scheduler task assignment frequency.
+//! Threshold of EMA difference is eluded by machine epsilon for floating point arithmetic errors.
+
+use crate::{load_balancer, placement};
+use core::fmt;
+use crossbeam_queue::ArrayQueue;
+use fmt::{Debug, Formatter};
+use lazy_static::lazy_static;
+use lever::prelude::TTas;
+use placement::CoreId;
+use std::collections::VecDeque;
+use std::time::Duration;
+use std::{
+    sync::{
+        atomic::{AtomicU64, Ordering},
+        Arc, Mutex,
+    },
+    thread::{self, Thread},
+};
+use tracing::{debug, trace};
+
+/// The default thread park timeout before checking for new tasks.
+const THREAD_PARK_TIMEOUT: Duration = Duration::from_millis(1);
+
+/// Frequency histogram's sliding window size.
+/// Defines how many frequencies will be considered for adaptation.
+const FREQUENCY_QUEUE_SIZE: usize = 10;
+
+/// If low watermark isn't configured this is the default scaler value.
+/// This value is used for the heuristics of the scaler
+const DEFAULT_LOW_WATERMARK: u64 = 2;
+
+/// Pool scaler interval time (milliseconds).
+/// This is the actual interval which makes adaptation calculation.
+const SCALER_POLL_INTERVAL: u64 = 90;
+
+/// Exponential moving average smoothing coefficient for limited window.
+/// Smoothing factor is estimated with: 2 / (N + 1) where N is sample size.
+const EMA_COEFFICIENT: f64 = 2_f64 / (FREQUENCY_QUEUE_SIZE as f64 + 1_f64);
+
+lazy_static! {
+    static ref ROUND_ROBIN_PIN: Mutex<CoreId> = Mutex::new(CoreId { id: 0 });
+}
+
+/// The `DynamicRunner` is piloted by `DynamicPoolManager`.
+/// Upon request it needs to be able to provide runner routines for:
+/// * Static threads.
+/// * Dynamic threads.
+/// * Standalone threads.
+///
+/// Your implementation of `DynamicRunner`
+/// will allow you to define what tasks must be accomplished.
+///
+/// Run static threads:
+///
+/// run_static should never return, and park for park_timeout instead.
+///
+/// Run dynamic threads:
+/// run_dynamic should never return, and call `parker()` when it has no more tasks to process.
+/// It will be unparked automatically by the `DynamicPoolManager` if needs be.
+///
+/// Run standalone threads:
+/// run_standalone should return once it has no more tasks to process.
+/// The `DynamicPoolManager` will spawn other standalone threads if needs be.
+pub trait DynamicRunner {
+    fn run_static(&self, park_timeout: Duration) -> !;
+    fn run_dynamic(&self, parker: &dyn Fn()) -> !;
+    fn run_standalone(&self);
+}
+
+/// The `DynamicPoolManager` is responsible for
+/// growing and shrinking a pool according to EMA rules.
+///
+/// It needs to be passed a structure that implements `DynamicRunner`,
+/// That will be responsible for actually spawning threads.
+///
+/// The `DynamicPoolManager` keeps track of the number
+/// of required number of threads to process load correctly.
+/// and depending on the current state it will case it will:
+/// - Spawn a lot of threads (we're predicting a load spike, and we need to prepare for it)
+/// - Spawn few threads (there's a constant load, and throughput is low because the current resources are busy)
+/// - Do nothing (the load is shrinking, threads will automatically stop once they're done).
+///
+/// Kinds of threads:
+///
+/// ## Static threads:
+/// Defined in the constructor, they will always be available. They park for `THREAD_PARK_TIMEOUT` on idle.
+///
+/// ## Dynamic threads:
+/// Created during `DynamicPoolManager` initialization, they will park on idle.
+/// The `DynamicPoolManager` grows the number of Dynamic threads
+/// so the total number of Static threads + Dynamic threads
+/// is the number of available cores on the machine. (`num_cpus::get()`)
+///
+/// ## Standalone threads:
+/// They are created when there aren't enough static and dynamic threads to process the expected load.
+/// They will be destroyed on idle.
+///
+/// ## Spawn order:
+/// In order to handle a growing load, the pool manager will ask to:
+/// - Use Static threads
+/// - Unpark Dynamic threads
+/// - Spawn Standalone threads
+///
+/// The pool manager is not responsible for the tasks to be performed by the threads, it's handled by the `DynamicRunner`
+///
+/// If you use tracing, you can have a look at the trace! logs generated by the structure.
+///
+pub struct DynamicPoolManager {
+    static_threads: usize,
+    dynamic_threads: usize,
+    parked_threads: ArrayQueue<Thread>,
+    runner: Arc<dyn DynamicRunner + Send + Sync>,
+    last_frequency: AtomicU64,
+    frequencies: TTas<VecDeque<u64>>,
+}
+
+impl Debug for DynamicPoolManager {
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        fmt.debug_struct("DynamicPoolManager")
+            .field("static_threads", &self.static_threads)
+            .field("dynamic_threads", &self.dynamic_threads)
+            .field("parked_threads", &self.parked_threads.len())
+            .field("parked_threads", &self.parked_threads.len())
+            .field("last_frequency", &self.last_frequency)
+            .field("frequencies", &self.frequencies.try_lock())
+            .finish()
+    }
+}
+
+impl DynamicPoolManager {
+    pub fn new(static_threads: usize, runner: Arc<dyn DynamicRunner + Send + Sync>) -> Self {
+        let dynamic_threads = 1.max(num_cpus::get().checked_sub(static_threads).unwrap_or(0));
+        Self {
+            static_threads,
+            dynamic_threads,
+            parked_threads: ArrayQueue::new(dynamic_threads),
+            runner,
+            last_frequency: AtomicU64::new(0),
+            frequencies: TTas::new(VecDeque::with_capacity(
+                FREQUENCY_QUEUE_SIZE.saturating_add(1),
+            )),
+        }
+    }
+
+    pub fn increment_frequency(&self) {
+        self.last_frequency.fetch_add(1, Ordering::Acquire);
+    }
+
+    /// Initialize the dynamic pool
+    /// That will be scaled
+    pub fn initialize(&'static self) {
+        // Static thread manager that will always be available
+        trace!("setting up the static thread manager");
+        (0..self.static_threads).for_each(|_| {
+            let clone = Arc::clone(&self.runner);
+            thread::Builder::new()
+                .name("bastion-driver-static".to_string())
+                .spawn(move || {
+                    Self::affinity_pinner();
+                    clone.run_static(THREAD_PARK_TIMEOUT);
+                })
+                .expect("couldn't spawn static thread");
+        });
+
+        // Dynamic thread manager that will allow us to unpark threads
+        // According to the needs
+        trace!("setting up the dynamic thread manager");
+        (0..self.dynamic_threads).for_each(|_| {
+            let clone = Arc::clone(&self.runner);
+            thread::Builder::new()
+                .name("bastion-driver-dynamic".to_string())
+                .spawn(move || {
+                    Self::affinity_pinner();
+                    clone.run_dynamic(&|| self.park_thread());
+                })
+                .expect("cannot start dynamic thread");
+        });
+
+        // Pool manager to check frequency of task rates
+        // and take action by scaling the pool accordingly.
+        thread::Builder::new()
+            .name("bastion-pool-manager".to_string())
+            .spawn(move || {
+                let poll_interval = Duration::from_millis(SCALER_POLL_INTERVAL);
+                trace!("setting up the pool manager");
+                loop {
+                    self.scale_pool();
+                    thread::park_timeout(poll_interval);
+                }
+            })
+            .expect("thread pool manager cannot be started");
+    }
+
+    /// Provision threads takes a number of threads that need to be made available.
+    /// It will try to unpark threads from the dynamic pool, and spawn more threads if needs be.
+    pub fn provision_threads(&'static self, n: usize) {
+        for i in 0..n {
+            if !self.unpark_thread() {
+                let new_threads = n - i;
+                trace!(
+                    "no more threads to unpark, spawning {} new threads",
+                    new_threads
+                );
+                return self.spawn_threads(new_threads);
+            }
+        }
+    }
+
+    fn spawn_threads(&'static self, n: usize) {
+        (0..n).for_each(|_| {
+            let clone = Arc::clone(&self.runner);
+            thread::Builder::new()
+                .name("bastion-blocking-driver-standalone".to_string())
+                .spawn(move || {
+                    Self::affinity_pinner();
+                    clone.run_standalone();
+                })
+                .unwrap();
+        })
+    }
+
+    /// Parks a thread until unpark_thread unparks it
+    pub fn park_thread(&self) {
+        let _ = self
+            .parked_threads
+            .push(std::thread::current())
+            .map(|_| {
+                trace!("parking thread {:?}", std::thread::current().id());
+                std::thread::park();
+            })
+            .map_err(|t| {
+                debug!("couldn't park thread {:?}", t.id(),);
+            });
+    }
+
+    /// Pops a thread from the parked_threads queue and unparks it.
+    /// returns true on success.
+    fn unpark_thread(&self) -> bool {
+        trace!("parked_threads: len is {}", self.parked_threads.len());
+        if let Some(thread) = self.parked_threads.pop() {
+            debug!("Executor: unpark_thread: unparking {:?}", thread.id());
+            thread.unpark();
+            true
+        } else {
+            false
+        }
+    }
+
+    ///
+    /// Affinity pinner for blocking pool
+    /// Pinning isn't going to be enabled for single core systems.
+    #[inline]
+    fn affinity_pinner() {
+        if 1 != *load_balancer::core_count() {
+            let mut core = ROUND_ROBIN_PIN.lock().unwrap();
+            placement::set_for_current(*core);
+            core.id = (core.id + 1) % *load_balancer::core_count();
+        }
+    }
+
+    /// Exponentially Weighted Moving Average calculation
+    ///
+    /// This allows us to find the EMA value.
+    /// This value represents the trend of tasks mapped onto the thread pool.
+    /// Calculation is following:
+    /// ```text
+    /// +--------+-----------------+----------------------------------+
+    /// | Symbol |   Identifier    |           Explanation            |
+    /// +--------+-----------------+----------------------------------+
+    /// | α      | EMA_COEFFICIENT | smoothing factor between 0 and 1 |
+    /// | Yt     | freq            | frequency sample at time t       |
+    /// | St     | acc             | EMA at time t                    |
+    /// +--------+-----------------+----------------------------------+
+    /// ```
+    /// Under these definitions formula is following:
+    /// ```text
+    /// EMA = α * [ Yt + (1 - α)*Yt-1 + ((1 - α)^2)*Yt-2 + ((1 - α)^3)*Yt-3 ... ] + St
+    /// ```
+    /// # Arguments
+    ///
+    /// * `freq_queue` - Sliding window of frequency samples
+    #[inline]
+    fn calculate_ema(freq_queue: &VecDeque<u64>) -> f64 {
+        freq_queue.iter().enumerate().fold(0_f64, |acc, (i, freq)| {
+            acc + ((*freq as f64) * ((1_f64 - EMA_COEFFICIENT).powf(i as f64) as f64))
+        }) * EMA_COEFFICIENT as f64
+    }
+
+    /// Adaptive pool scaling function
+    ///
+    /// This allows to spawn new threads to make room for incoming task pressure.
+    /// Works in the background detached from the pool system and scales up the pool based
+    /// on the request rate.
+    ///
+    /// It uses frequency based calculation to define work. Utilizing average processing rate.
+    fn scale_pool(&'static self) {
+        // Fetch current frequency, it does matter that operations are ordered in this approach.
+        let current_frequency = self.last_frequency.swap(0, Ordering::SeqCst);
+        let mut freq_queue = self.frequencies.lock();
+
+        // Make it safe to start for calculations by adding initial frequency scale
+        if freq_queue.len() == 0 {
+            freq_queue.push_back(0);
+        }
+
+        // Calculate message rate for the given time window
+        let frequency = (current_frequency as f64 / SCALER_POLL_INTERVAL as f64) as u64;
+
+        // Calculates current time window's EMA value (including last sample)
+        let prev_ema_frequency = Self::calculate_ema(&freq_queue);
+
+        // Add seen frequency data to the frequency histogram.
+        freq_queue.push_back(frequency);
+        if freq_queue.len() == FREQUENCY_QUEUE_SIZE.saturating_add(1) {
+            freq_queue.pop_front();
+        }
+
+        // Calculates current time window's EMA value (including last sample)
+        let curr_ema_frequency = Self::calculate_ema(&freq_queue);
+
+        // Adapts the thread count of pool
+        //
+        // Sliding window of frequencies visited by the pool manager.
+        // Pool manager creates EMA value for previous window and current window.
+        // Compare them to determine scaling amount based on the trends.
+        // If current EMA value is bigger, we will scale up.
+        if curr_ema_frequency > prev_ema_frequency {
+            // "Scale by" amount can be seen as "how much load is coming".
+            // "Scale" amount is "how many threads we should spawn".
+            let scale_by: f64 = curr_ema_frequency - prev_ema_frequency;
+            let scale = num_cpus::get().min(
+                ((DEFAULT_LOW_WATERMARK as f64 * scale_by) + DEFAULT_LOW_WATERMARK as f64) as usize,
+            );
+            trace!("unparking {} threads", scale);
+
+            // It is time to scale the pool!
+            self.provision_threads(scale);
+        } else if (curr_ema_frequency - prev_ema_frequency).abs() < std::f64::EPSILON
+            && current_frequency != 0
+        {
+            // Throughput is low. Allocate more threads to unblock flow.
+            // If we fall to this case, scheduler is congested by longhauling tasks.
+            // For unblock the flow we should add up some threads to the pool, but not that many to
+            // stagger the program's operation.
+            trace!("unparking {} threads", DEFAULT_LOW_WATERMARK);
+            self.provision_threads(DEFAULT_LOW_WATERMARK as usize);
+        }
+    }
+}
diff --git a/src/bastion-executor/src/worker.rs b/src/bastion-executor/src/worker.rs
index eb1a9b73..d97e260a 100644
--- a/src/bastion-executor/src/worker.rs
+++ b/src/bastion-executor/src/worker.rs
@@ -3,13 +3,17 @@
 //!
 //! This worker implementation relies on worker run queue statistics which are hold in the pinned global memory
 //! where workload distribution calculated and amended to their own local queues.
-use crate::load_balancer;
-use crate::pool::{self, Pool};
-use crate::run_queue::{Steal, Worker};
+
+use crate::pool;
+
 use lightproc::prelude::*;
-use load_balancer::SmpStats;
-use std::cell::{Cell, UnsafeCell};
-use std::{iter, ptr};
+use std::cell::Cell;
+use std::ptr;
+use std::time::Duration;
+
+/// The timeout we'll use when parking before an other Steal attempt
+pub const THREAD_PARK_TIMEOUT: Duration = Duration::from_millis(1);
+
 ///
 /// Get the current process's stack
 pub fn current() -> ProcStack {
@@ -55,97 +59,6 @@ where
     }
 }
 
-thread_local! {
-    static QUEUE: UnsafeCell<Option<Worker<LightProc>>> = UnsafeCell::new(None);
-}
-
 pub(crate) fn schedule(proc: LightProc) {
-    QUEUE.with(|queue| {
-        let local = unsafe { (*queue.get()).as_ref() };
-
-        match local {
-            None => pool::get().injector.push(proc),
-            Some(q) => q.push(proc),
-        }
-    });
-
-    pool::get().sleepers.notify_one();
-}
-
-///
-/// Fetch the process from the run queue.
-/// Does the work of work-stealing if process doesn't exist in the local run queue.
-pub fn fetch_proc(affinity: usize) -> Option<LightProc> {
-    let pool = pool::get();
-
-    QUEUE.with(|queue| {
-        let local = unsafe { (*queue.get()).as_ref().unwrap() };
-        local.pop().or_else(|| affine_steal(pool, local, affinity))
-    })
-}
-
-fn affine_steal(pool: &Pool, local: &Worker<LightProc>, affinity: usize) -> Option<LightProc> {
-    let load_mean = load_balancer::stats().mean();
-    // Pop a task from the local queue, if not empty.
-    local.pop().or_else(|| {
-        // Otherwise, we need to look for a task elsewhere.
-        iter::repeat_with(|| {
-            let core_vec = load_balancer::stats().get_sorted_load();
-
-            // First try to get procs from global queue
-            pool.injector.steal_batch_and_pop(&local).or_else(|| {
-                match core_vec.get(0) {
-                    Some((core, _)) => {
-                        // If affinity is the one with the highest let other's do the stealing
-                        if *core == affinity {
-                            Steal::Retry
-                        } else {
-                            // Try iterating through biggest to smallest
-                            core_vec
-                                .iter()
-                                .map(|s| {
-                                    // Steal the mean amount to balance all queues considering incoming workloads
-                                    // Otherwise do an ignorant steal (which is going to be useless)
-                                    if load_mean > 0 {
-                                        pool.stealers
-                                            .get(s.0)
-                                            .unwrap()
-                                            .steal_batch_and_pop_with_amount(&local, load_mean)
-                                    } else {
-                                        pool.stealers.get(s.0).unwrap().steal_batch_and_pop(&local)
-                                        // TODO: Set evacuation flag in thread_local
-                                    }
-                                })
-                                .collect()
-                        }
-                    }
-                    _ => Steal::Retry,
-                }
-            })
-        })
-        // Loop while no task was stolen and any steal operation needs to be retried.
-        .find(|s| !s.is_retry())
-        // Extract the stolen task, if there is one.
-        .and_then(|s| s.success())
-    })
-}
-
-pub(crate) fn stats_generator(affinity: usize, local: &Worker<LightProc>) {
-    load_balancer::stats().store_load(affinity, local.worker_run_queue_size());
-}
-
-pub(crate) fn main_loop(affinity: usize, local: Worker<LightProc>) {
-    QUEUE.with(|queue| unsafe { *queue.get() = Some(local) });
-
-    loop {
-        QUEUE.with(|queue| {
-            let local = unsafe { (*queue.get()).as_ref().unwrap() };
-            stats_generator(affinity, local);
-        });
-
-        match fetch_proc(affinity) {
-            Some(proc) => set_stack(proc.stack(), || proc.run()),
-            None => pool::get().sleepers.wait(),
-        }
-    }
+    pool::schedule(proc)
 }
diff --git a/src/bastion-executor/tests/lib.rs b/src/bastion-executor/tests/lib.rs
index 2a3c9f8b..416c571c 100644
--- a/src/bastion-executor/tests/lib.rs
+++ b/src/bastion-executor/tests/lib.rs
@@ -8,8 +8,19 @@ mod tests {
         dbg!(core_ids);
     }
 
-    #[test]
-    fn pool_check() {
-        pool::get();
+    #[cfg(feature = "tokio-runtime")]
+    mod tokio_tests {
+        #[tokio::test]
+        async fn pool_check() {
+            super::pool::get();
+        }
+    }
+
+    #[cfg(not(feature = "tokio-runtime"))]
+    mod no_tokio_tests {
+        #[test]
+        fn pool_check() {
+            super::pool::get();
+        }
     }
 }
diff --git a/src/bastion-executor/tests/run_blocking.rs b/src/bastion-executor/tests/run_blocking.rs
new file mode 100644
index 00000000..6f792957
--- /dev/null
+++ b/src/bastion-executor/tests/run_blocking.rs
@@ -0,0 +1,38 @@
+use bastion_executor::blocking;
+use bastion_executor::run::run;
+use lightproc::proc_stack::ProcStack;
+use std::thread;
+use std::time::Duration;
+
+#[cfg(feature = "tokio-runtime")]
+mod tokio_tests {
+    #[tokio::test]
+    async fn test_run_blocking() {
+        super::run_test()
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod no_tokio_tests {
+    #[test]
+    fn test_run_blocking() {
+        super::run_test()
+    }
+}
+
+fn run_test() {
+    let output = run(
+        blocking::spawn_blocking(
+            async {
+                let duration = Duration::from_millis(1);
+                thread::sleep(duration);
+                42
+            },
+            ProcStack::default(),
+        ),
+        ProcStack::default(),
+    )
+    .unwrap();
+
+    assert_eq!(42, output);
+}
diff --git a/src/bastion/Cargo.toml b/src/bastion/Cargo.toml
index 429dd26d..b0fbb65e 100644
--- a/src/bastion/Cargo.toml
+++ b/src/bastion/Cargo.toml
@@ -5,7 +5,7 @@ name = "bastion"
 # - Update CHANGELOG.md.
 #   - npm install -g auto-changelog && auto-changelog at the root
 # - Create "v0.x.y" git tag at the root of the project.
-version = "0.4.3-alpha.0"
+version = "0.4.5-alpha.0"
 description = "Fault-tolerant Runtime for Rust applications"
 authors = ["Mahmut Bulut <vertexclique@gmail.com>"]
 keywords = ["fault-tolerant", "runtime", "actor", "system"]
@@ -43,19 +43,20 @@ distributed = [
 ]
 scaling = []
 docs = ["distributed", "scaling", "default"]
-
+tokio-runtime = ["bastion-executor/tokio-runtime"]
 
 [package.metadata.docs.rs]
 features = ["docs"]
 rustdoc-args = ["--cfg", "feature=\"docs\""]
 
 [dependencies]
-bastion-executor = "0.3.6"
-lightproc = "0.3.5"
-# bastion-executor = { version = "= 0.3.7-alpha.0", path = "../bastion-executor" }
-# lightproc = { version = "= 0.3.6-alpha.0", path = "../lightproc" }
+bastion-executor = { git = "https://github.com/bastion-rs/bastion.git" }
+# bastion-executor = { path = "../bastion-executor" }
+lightproc =  { git = "https://github.com/bastion-rs/bastion.git" }
+# lightproc = "0.3"
+# lightproc = { path = "../lightproc" }
 
-lever = "0.1.1-alpha.11"
+lever = "0.1"
 futures = "0.3.5"
 futures-timer = "3.0.2"
 fxhash = "0.2"
@@ -64,7 +65,7 @@ serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 pin-utils = "0.1"
 
-async-mutex = "1.1"
+async-mutex = "1.4.0"
 uuid = { version = "0.8", features = ["v4"] }
 
 # Distributed
@@ -73,17 +74,32 @@ artillery-core = { version = "0.1.2-alpha.3", optional = true }
 # Log crates
 tracing-subscriber = "0.2.6"
 tracing = "0.1.15"
-anyhow = "1.0.31"
+anyhow = "1.0"
+crossbeam-queue = "0.3.0"
+log = "0.4.14"
+lasso = {version = "0.5", features = ["multi-threaded"] }
+once_cell = "1.7.2"
+thiserror = "1.0.24"
+async-channel = "1.6.1"
+regex = "1.4.5"
+async-trait = "0.1.48"
+crossbeam = "0.8.0"
 
 [target.'cfg(not(windows))'.dependencies]
-nuclei = "0.1.2-alpha.1"
+nuclei = "0.1"
 
 [dev-dependencies]
-env_logger = "0.7"
-proptest = "0.10"
+env_logger = "0.8"
+proptest = "1.0"
 snap = "1.0"
 # prime_numbers example
 bastion-utils = { version = "0.3.2", path = "../bastion-utils" }
-rand = "0.7.3"
+rand = "0.8"
 rayon = "1.3.1"
 num_cpus = "1.13.0"
+# hello_tokio example
+tokio = { version="1.1", features = ["time", "macros"] }
+# bastion-executor = { path = "../bastion-executor" }
+bastion-executor = { git = "https://github.com/bastion-rs/bastion.git" }
+once_cell = "1.5.2"
+tokio-test = "0.4.0"
diff --git a/src/bastion/examples/broadcast_message.rs b/src/bastion/examples/broadcast_message.rs
index 51094574..35898942 100644
--- a/src/bastion/examples/broadcast_message.rs
+++ b/src/bastion/examples/broadcast_message.rs
@@ -14,12 +14,12 @@ use tracing::Level;
 /// broadcasting messages features.
 ///
 /// The pipeline in this example can be described in the following way:
-/// 1. The Input group contains the only one actor that stars the processing with
+/// 1. The Input group contains the only one actor that starts the processing with
 ///    sending messages through a dispatcher to actors in the Map group.
 /// 2. Each actor of the Process group does some useful work and passes a result
 ///    to the next stage with the similar call to the Reduce group.
 /// 3. The actor from the Response group retrieves the data from the actors of the
-///    Reduce group, combines the results and prints its when everything is done.
+///    Reduce group, combines the results and prints them when everything is done.
 ///
 fn main() {
     let subscriber = tracing_subscriber::fmt()
@@ -32,16 +32,16 @@ fn main() {
 
     Bastion::init();
 
-    Bastion::supervisor(input_supervisor)
+    Bastion::supervisor(response_supervisor)
         .and_then(|_| Bastion::supervisor(map_supervisor))
-        .and_then(|_| Bastion::supervisor(response_supervisor))
+        .and_then(|_| Bastion::supervisor(input_supervisor))
         .expect("Couldn't create supervisor chain.");
 
     Bastion::start();
     Bastion::block_until_stopped();
 }
 
-// Supervisor that tracking only the single actor with input data
+// Supervisor which tracks only the single actor with input data
 fn input_supervisor(supervisor: Supervisor) -> Supervisor {
     supervisor.children(input_group)
 }
@@ -59,7 +59,7 @@ fn response_supervisor(supervisor: Supervisor) -> Supervisor {
 fn input_group(children: Children) -> Children {
     children.with_name("input").with_redundancy(1).with_exec(
         move |ctx: BastionContext| async move {
-            println!("[Input] Worker started!");
+            tracing::info!("[Input] Worker started!");
 
             let data = vec!["A B C", "A C C", "B C C"];
             let group_name = "Processing".to_string();
@@ -83,11 +83,11 @@ fn process_group(children: Children) -> Children {
             // the namespace with the "Map" name and removed after being stopped or killed
             // automatically.
             //
-            // If needed to use more than one groups, then do more `with_dispatcher` calls
+            // If needed to use more than one group, then do more `with_dispatcher` calls
             Dispatcher::with_type(DispatcherType::Named("Processing".to_string())),
         )
         .with_exec(move |ctx: BastionContext| async move {
-            println!("[Processing] Worker started!");
+            tracing::info!("[Processing] Worker started!");
 
             msg! { ctx.recv().await?,
                 // We received the message from other actor wrapped in Arc<T>
@@ -128,14 +128,14 @@ fn response_group(children: Children) -> Children {
         .with_redundancy(1)
         .with_dispatcher(
             // We will re-use the dispatcher to make the example easier to understand
-            // and flexibility in code.
+            // and increase flexibility in code.
             //
-            // The single difference is only the name for Dispatcher for our actor's group.
+            // The single difference is only the name for Dispatcher for our actors group.
             Dispatcher::with_type(DispatcherType::Named("Response".to_string())),
         )
         .with_exec(move |ctx: BastionContext| {
             async move {
-                println!("[Response] Worker started!");
+                tracing::info!("[Response] Worker started!");
 
                 let mut received_messages = 0;
                 let expected_messages = 3;
diff --git a/src/bastion/examples/distributed-fwrite.rs b/src/bastion/examples/distributed-fwrite.rs
index 76ec7e77..f5c2786b 100644
--- a/src/bastion/examples/distributed-fwrite.rs
+++ b/src/bastion/examples/distributed-fwrite.rs
@@ -1,11 +1,16 @@
-use bastion::prelude::*;
-use futures::*;
-use std::fs::{File, OpenOptions};
+#[cfg(not(target_os = "windows"))]
+use std::fs::File;
+use std::fs::OpenOptions;
 #[cfg(target_os = "windows")]
 use std::io::Write;
 use std::path::PathBuf;
 use std::sync::Arc;
 
+#[cfg(not(target_os = "windows"))]
+use futures::*;
+
+use bastion::prelude::*;
+
 ///
 /// Parallel (MapReduce) job which async writes results to a single output file
 ///
@@ -48,7 +53,6 @@ fn main() {
     // Get a shadowed sharable reference of workers.
     let workers = Arc::new(workers);
 
-    //
     // Mapper that generates work.
     Bastion::children(|children: Children| {
         children.with_exec(move |ctx: BastionContext| {
@@ -60,6 +64,11 @@ fn main() {
                 path.push("data");
                 path.push("distwrite");
 
+                if !path.exists() || !path.is_file() {
+                    Bastion::stop();
+                    panic!("The file could not be opened.");
+                }
+
                 let fo = OpenOptions::new()
                     .read(true)
                     .write(true)
diff --git a/src/bastion/examples/distributor.rs b/src/bastion/examples/distributor.rs
new file mode 100644
index 00000000..5ebf7b4b
--- /dev/null
+++ b/src/bastion/examples/distributor.rs
@@ -0,0 +1,267 @@
+///! Create a conference.
+///!
+///! 1st Group
+///! Staff (5) - Going to organize the event // OK
+///!
+///! 2nd Group
+///! Enthusiasts (50) - interested in participating to the conference (haven't registered yet) // OK
+///!
+///! 3rd Group
+///! Attendees (empty for now) - Participate
+///!
+///! Enthusiast -> Ask one of the staff members "when is the conference going to happen ?" // OK
+///! Broadcast / Question => Answer 0 or 1 Staff members are going to reply eventually? // OK
+///!
+///! Staff -> Send a Leaflet to all of the enthusiasts, letting them know that they can register. // OK
+///!
+///! "hey conference <awesomeconference> is going to happen. will you be there?"
+///! Broadcast / Question -> if people reply with YES => fill the 3rd group
+///! some enthusiasts are now attendees
+///!
+///! Staff -> send the actual schedule and misc infos to Attendees
+///! Broadcast / Statement (Attendees)
+///!
+///! An attendee sends a thank you note to one staff member (and not bother everyone)
+///! One message / Statement (Staff) // OK
+///!
+///! ```rust
+///!     let staff = Distributor::named("staff");
+///!     let enthusiasts = Distributor::named("enthusiasts");
+///!     let attendees = Disitributor::named("attendees");
+///!     // Enthusiast -> Ask the whole staff "when is the conference going to happen ?"
+///!     ask_one(Message + Clone) -> Result<impl Future<Output = Reply>, CouldNotSendError>
+///!     // await_one // await_all
+///!     // first ? means "have we been able to send the question?"
+///!     // it s in a month
+///!     let replies = staff.ask_one("when is the conference going to happen ?")?.await?;
+///!     ask_everyone(Message + Clone) -> Result<impl Stream<Item = Reply>, CouldNotSendError>
+///!     let participants = enthusiasts.ask_everyone("here's our super nice conference, it s happening people!").await?;
+///!     for participant in participants {
+///!         // grab the sender and add it to the attendee recipient group
+///!     }
+///!     // send the schedule
+///!     tell_everyone(Message + Clone) -> Result<(), CouldNotSendError>
+///!     attendees.tell_everyone("hey there, conf is in a week, here s where and how it s going to happen")?;
+///!     // send a thank you note
+///!     tell(Message) -> Result<(), CouldNotSendError>
+///!     staff.tell_one("thank's it was amazing")?;
+///!     children
+///!         .with_redundancy(10)
+///!         .with_distributor(Distributor::named("staff"))
+///!         // We create the function to exec when each children is called
+///!         .with_exec(move |ctx: BastionContext| async move { /* ... */ })
+///!     children
+///!         .with_redundancy(100)
+///!         .with_distributor(Distributor::named("enthusiasts"))
+///!         // We create the function to exec when each children is called
+///!         .with_exec(move |ctx: BastionContext| async move { /* ... */ })
+///!     children
+///!         .with_redundancy(0)
+///!         .with_distributor(Distributor::named("attendees"))
+///!         // We create the function to exec when each children is called
+///!         .with_exec(move |ctx: BastionContext| async move { /* ... */ })
+///! ```
+use anyhow::{anyhow, Context, Result as AnyResult};
+use bastion::distributor::*;
+use bastion::prelude::*;
+use tracing::Level;
+
+// true if the person attends the conference
+#[derive(Debug)]
+struct RSVP {
+    attends: bool,
+    child_ref: ChildRef,
+}
+
+#[derive(Debug, Clone)]
+struct ConferenceSchedule {
+    start: std::time::Duration,
+    end: std::time::Duration,
+    misc: String,
+}
+
+/// cargo r --features=tokio-runtime --example distributor
+#[cfg(feature = "tokio-runtime")]
+#[tokio::main]
+async fn main() -> AnyResult<()> {
+    run()
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+fn main() -> AnyResult<()> {
+    run()
+}
+
+fn run() -> AnyResult<()> {
+    let subscriber = tracing_subscriber::fmt()
+        .with_max_level(Level::INFO)
+        .finish();
+    tracing::subscriber::set_global_default(subscriber).unwrap();
+
+    // Initialize bastion
+    Bastion::init();
+
+    // 1st Group
+    Bastion::supervisor(|supervisor| {
+        supervisor.children(|children| {
+            // Iniit staff
+            // Staff (5 members) - Going to organize the event
+            children
+                .with_redundancy(5)
+                .with_distributor(Distributor::named("staff"))
+                .with_exec(organize_the_event)
+        })
+    })
+    // 2nd Group
+    .and_then(|_| {
+        Bastion::supervisor(|supervisor| {
+            supervisor.children(|children| {
+                // Enthusiasts (50) - interested in participating to the conference (haven't registered yet)
+                children
+                    .with_redundancy(50)
+                    .with_distributor(Distributor::named("enthusiasts"))
+                    .with_exec(be_interested_in_the_conference)
+            })
+        })
+    })
+    .map_err(|_| anyhow!("couldn't setup the bastion"))?;
+
+    Bastion::start();
+
+    // Wait a bit until everyone is ready
+    sleep(std::time::Duration::from_secs(5));
+
+    let staff = Distributor::named("staff");
+    let enthusiasts = Distributor::named("enthusiasts");
+    let attendees = Distributor::named("attendees");
+
+    // Enthusiast -> Ask one of the staff members "when is the conference going to happen ?"
+    let reply: Result<String, SendError> = run!(async {
+        staff
+            .request("when is the next conference going to happen?")
+            .await
+            .expect("couldn't receive reply")
+    });
+
+    tracing::error!("{:?}", reply); // Ok("Next month!")
+
+    // "hey conference <awesomeconference> is going to happen. will you be there?"
+    // Broadcast / Question -> if people reply with YES => fill the 3rd group
+    let answers = enthusiasts
+        .ask_everyone("hey, the conference is going to happen, will you be there?")
+        .expect("couldn't ask everyone");
+
+    for answer in answers.into_iter() {
+        run!(async move {
+            MessageHandler::new(answer.await.expect("couldn't receive reply"))
+                .on_tell(|rsvp: RSVP, _| {
+                    if rsvp.attends {
+                        tracing::info!("{:?} will be there! :)", rsvp.child_ref.id());
+                        attendees
+                            .subscribe(rsvp.child_ref)
+                            .expect("couldn't subscribe attendee");
+                    } else {
+                        tracing::error!("{:?} won't make it :(", rsvp.child_ref.id());
+                    }
+                })
+                .on_fallback(|unknown, _sender_addr| {
+                    tracing::error!(
+                        "distributor_test: uh oh, I received a message I didn't understand\n {:?}",
+                        unknown
+                    );
+                });
+        });
+    }
+
+    // Ok now that attendees have subscribed, let's send information around!
+    tracing::info!("Let's send invitations!");
+    // Staff -> send the actual schedule and misc infos to Attendees
+    let total_sent = attendees
+        .tell_everyone(ConferenceSchedule {
+            start: std::time::Duration::from_secs(60),
+            end: std::time::Duration::from_secs(3600),
+            misc: "it's going to be amazing!".to_string(),
+        })
+        .context("couldn't let everyone know the conference is available!")?;
+
+    tracing::error!("total number of attendees: {}", total_sent.len());
+
+    tracing::info!("the conference is running!");
+
+    // Let's wait until the conference is over 8D
+    sleep(std::time::Duration::from_secs(5));
+
+    // An attendee sends a thank you note to one staff member (and not bother everyone)
+    staff
+        .tell_one("the conference was amazing thank you so much!")
+        .context("couldn't thank the staff members :(")?;
+
+    // And we're done!
+    Bastion::stop();
+
+    // BEWARE, this example doesn't return
+    Bastion::block_until_stopped();
+
+    Ok(())
+}
+
+async fn organize_the_event(ctx: BastionContext) -> Result<(), ()> {
+    loop {
+        MessageHandler::new(ctx.recv().await?)
+            .on_question(|message: &str, sender| {
+                tracing::info!("received a question: \n{}", message);
+                sender.reply("Next month!".to_string()).unwrap();
+            })
+            .on_tell(|message: &str, _| {
+                tracing::info!("received a message: \n{}", message);
+            })
+            .on_fallback(|unknown, _sender_addr| {
+                tracing::error!(
+                    "staff: uh oh, I received a message I didn't understand\n {:?}",
+                    unknown
+                );
+            });
+    }
+}
+
+async fn be_interested_in_the_conference(ctx: BastionContext) -> Result<(), ()> {
+    loop {
+        MessageHandler::new(ctx.recv().await?)
+            .on_tell(|message: std::sync::Arc<&str>, _| {
+                tracing::info!(
+                    "child {}, received a broadcast message:\n{}",
+                    ctx.current().id(),
+                    message
+                );
+            })
+            .on_tell(|schedule: ConferenceSchedule, _| {
+                tracing::info!(
+                    "child {}, received broadcast conference schedule!:\n{:?}",
+                    ctx.current().id(),
+                    schedule
+                );
+            })
+            .on_question(|message: &str, sender| {
+                tracing::info!("received a question: \n{}", message);
+                // ILL BE THERE!
+                sender
+                    .reply(RSVP {
+                        attends: rand::random(),
+                        child_ref: ctx.current().clone(),
+                    })
+                    .unwrap();
+            });
+    }
+}
+
+#[cfg(feature = "tokio-runtime")]
+fn sleep(duration: std::time::Duration) {
+    run!(async {
+        tokio::time::sleep(duration).await;
+    });
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+fn sleep(duration: std::time::Duration) {
+    std::thread::sleep(duration);
+}
diff --git a/src/bastion/examples/fibonacci_message_handler.rs b/src/bastion/examples/fibonacci_message_handler.rs
new file mode 100644
index 00000000..e6ca7220
--- /dev/null
+++ b/src/bastion/examples/fibonacci_message_handler.rs
@@ -0,0 +1,147 @@
+use bastion::prelude::*;
+
+use tracing::{error, info};
+
+// This terribly slow implementation
+// will allow us to be rough on the cpu
+fn fib(n: usize) -> usize {
+    if n == 0 || n == 1 {
+        n
+    } else {
+        fib(n - 1) + fib(n - 2)
+    }
+}
+
+// This terrible helper is converting `fib 50` into a tuple ("fib", 50)
+// we might want to use actual serializable / deserializable structures
+// in the real world
+fn deserialize_into_fib_command(message: String) -> (String, usize) {
+    let arguments: Vec<&str> = message.split(' ').collect();
+    let command = arguments.first().map(|s| s.to_string()).unwrap_or_default();
+    let number = usize::from_str_radix(arguments.get(1).unwrap_or(&"0"), 10).unwrap_or(0);
+    (command, number)
+}
+
+// This is the heavylifting.
+// A child will wait for a message, and try to process it.
+async fn fib_child_task(ctx: BastionContext) -> Result<(), ()> {
+    loop {
+        MessageHandler::new(ctx.recv().await?)
+            .on_question(|request: String, sender| {
+                let (command, number) = deserialize_into_fib_command(request);
+                if command == "fib" {
+                    sender
+                        .reply(format!("{}", fib(number)))
+                        .expect("couldn't reply :(");
+                } else {
+                    sender
+                        .reply(format!(
+                            "I'm sorry I didn't understand the task I was supposed to do"
+                        ))
+                        .expect("couldn't reply :(");
+                }
+            })
+            .on_broadcast(|broadcast: &String, _sender_addr| {
+                info!("received broadcast: {:?}", *broadcast);
+            })
+            .on_tell(|message: String, _sender_addr| {
+                info!("someone told me something: {}", message);
+            })
+            .on_fallback(|unknown, _sender_addr| {
+                error!(
+                    "uh oh, I received a message I didn't understand\n {:?}",
+                    unknown
+                );
+            });
+    }
+}
+
+// This little helper allows me to send a request, and get a reply.
+// The types are `String` for this quick example, but there's a way for us to do better.
+// We will see this in other examples.
+async fn request(child: &ChildRef, body: String) -> std::io::Result<String> {
+    let answer = child
+        .ask_anonymously(body)
+        .expect("couldn't perform request");
+
+    Ok(
+        MessageHandler::new(answer.await.expect("couldn't receive answer"))
+            .on_tell(|reply, _sender_addr| reply)
+            .on_fallback(|unknown, _sender_addr| {
+                error!(
+                    "uh oh, I received a message I didn't understand: {:?}",
+                    unknown
+                );
+                "".to_string()
+            }),
+    )
+}
+
+// RUST_LOG=info cargo run --example fibonacci_message_handler
+fn main() {
+    // This will allow us to have nice colored logs when we run the program
+    env_logger::init();
+
+    // We need a bastion in order to run everything
+    Bastion::init();
+    Bastion::start();
+
+    // Spawn 4 children that will execute our fibonacci task
+    let children =
+        Bastion::children(|children| children.with_redundancy(4).with_exec(fib_child_task))
+            .expect("couldn't create children");
+
+    // Broadcasting 1 message to the children
+    // Have a look at the console output
+    // to see 1 log entry for each child!
+    children
+        .broadcast("Hello there :)".to_string())
+        .expect("Couldn't broadcast to the children.");
+
+    let mut fib_to_compute = 35;
+    for child in children.elems() {
+        child
+            .tell_anonymously("shhh here's a message, don't tell anyone.".to_string())
+            .expect("Couldn't whisper to child.");
+
+        let now = std::time::Instant::now();
+        // by using run!, we are blocking.
+        // we could have used spawn! instead,
+        // to run everything in parallel.
+        let fib_reply = run!(request(child, format!("fib {}", fib_to_compute)))
+            .expect("send_command_to_child failed");
+
+        println!(
+            "fib({}) = {} - Computed in {}ms",
+            fib_to_compute,
+            fib_reply,
+            now.elapsed().as_millis()
+        );
+        // Let's not go too far with the fib sequence
+        // Otherwise the computer may take a while!
+        fib_to_compute += 2;
+    }
+    Bastion::stop();
+    Bastion::block_until_stopped();
+}
+
+// Compiling bastion v0.3.5-alpha (/home/ignition/Projects/oss/bastion/src/bastion)
+// Finished dev [unoptimized + debuginfo] target(s) in 1.07s
+//  Running `target/debug/examples/fibonacci`
+// [2020-05-08T14:00:53Z INFO  bastion::system] System: Initializing.
+// [2020-05-08T14:00:53Z INFO  bastion::system] System: Launched.
+// [2020-05-08T14:00:53Z INFO  bastion::system] System: Starting.
+// [2020-05-08T14:00:53Z INFO  bastion::system] System: Launching Supervisor(00000000-0000-0000-0000-000000000000).
+// [2020-05-08T14:00:53Z INFO  fibonacci] someone told me something: shhh here's a message, don't tell anyone.
+// [2020-05-08T14:00:53Z INFO  fibonacci] received broadcast: "Hello there :)"
+// [2020-05-08T14:00:53Z INFO  fibonacci] received broadcast: "Hello there :)"
+// [2020-05-08T14:00:53Z INFO  fibonacci] received broadcast: "Hello there :)"
+// fib(35) = 9227465 - Computed in 78ms
+// [2020-05-08T14:00:53Z INFO  fibonacci] received broadcast: "Hello there :)"
+// [2020-05-08T14:00:53Z INFO  fibonacci] someone told me something: shhh here's a message, don't tell anyone.
+// fib(37) = 24157817 - Computed in 196ms
+// [2020-05-08T14:00:53Z INFO  fibonacci] someone told me something: shhh here's a message, don't tell anyone.
+// fib(39) = 63245986 - Computed in 512ms
+// [2020-05-08T14:00:54Z INFO  fibonacci] someone told me something: shhh here's a message, don't tell anyone.
+// fib(41) = 165580141 - Computed in 1327ms
+// [2020-05-08T14:00:55Z INFO  bastion::system] System: Stopping.
diff --git a/src/bastion/examples/hello_tokio.rs b/src/bastion/examples/hello_tokio.rs
new file mode 100644
index 00000000..57d88ab6
--- /dev/null
+++ b/src/bastion/examples/hello_tokio.rs
@@ -0,0 +1,104 @@
+#[cfg(feature = "tokio-runtime")]
+use anyhow::Result as AnyResult;
+#[cfg(feature = "tokio-runtime")]
+use bastion::prelude::*;
+#[cfg(feature = "tokio-runtime")]
+use tokio;
+#[cfg(feature = "tokio-runtime")]
+use tracing::{error, warn, Level};
+
+/// `cargo run --features=tokio-runtime --example hello_tokio`
+///
+/// We are focusing on the contents of the msg! macro here.
+/// If you would like to understand how the rest works,
+/// Have a look at the `hello_world.rs` example instead :)
+///
+/// Log output:
+///
+/// Jan 31 14:55:55.677  WARN hello_tokio: just spawned!
+/// Jan 31 14:55:56.678  WARN hello_tokio: Ok let's handle a message now.
+/// Jan 31 14:55:56.678 ERROR hello_tokio: just received hello, world!
+/// Jan 31 14:55:56.678  WARN hello_tokio: sleeping for 2 seconds without using the bastion executor
+/// Jan 31 14:55:58.680  WARN hello_tokio: and done!
+/// Jan 31 14:55:58.681  WARN hello_tokio: let's sleep for 5 seconds within a blocking block
+/// Jan 31 14:56:03.682  WARN hello_tokio: awaited 5 seconds
+/// Jan 31 14:56:03.682 ERROR hello_tokio: waited for the blocking! to be complete!
+/// Jan 31 14:56:03.682 ERROR hello_tokio: not waiting for spawn! to be complete, moving on!
+/// Jan 31 14:56:03.683  WARN hello_tokio: let's sleep for 10 seconds within a spawn block
+/// Jan 31 14:56:13.683  WARN hello_tokio: the spawn! is complete
+/// Jan 31 14:56:15.679  WARN hello_tokio: we're done, stopping the bastion!
+#[cfg(feature = "tokio-runtime")]
+#[tokio::main]
+async fn main() -> AnyResult<()> {
+    // Initialize tracing logger
+    // so we get nice output on the console.
+    let subscriber = tracing_subscriber::fmt()
+        .with_max_level(Level::WARN)
+        .finish();
+    tracing::subscriber::set_global_default(subscriber).unwrap();
+
+    Bastion::init();
+    Bastion::start();
+    let workers = Bastion::children(|children| {
+        children.with_exec(|ctx: BastionContext| {
+            async move {
+                warn!("just spawned!");
+                tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+                warn!("Ok let's handle a message now.");
+                msg! {
+                    ctx.recv().await?,
+                    msg: &'static str => {
+                        // Printing the incoming msg
+                        error!("just received {}", msg);
+
+                        warn!("sleeping for 2 seconds without using the bastion executor");
+                        tokio::time::sleep(std::time::Duration::from_secs(2)).await;
+                        warn!("and done!");
+
+                        // let's wait until a tokio powered future is complete
+                        run!(blocking! {
+                            warn!("let's sleep for 5 seconds within a blocking block");
+                            tokio::time::sleep(std::time::Duration::from_secs(5)).await;
+                            warn!("awaited 5 seconds");
+                        });
+                        error!("waited for the blocking! to be complete!");
+
+                        // let's spawn a tokio powered future and move on
+                        spawn! {
+                            warn!("let's sleep for 10 seconds within a spawn block");
+                            tokio::time::sleep(std::time::Duration::from_secs(10)).await;
+                            warn!("the spawn! is complete");
+                        };
+                        error!("not waiting for spawn! to be complete, moving on!");
+                    };
+                    _: _ => ();
+                }
+                Ok(())
+            }
+        })
+    })
+    .expect("Couldn't create the children group.");
+
+    let asker = async {
+        workers.elems()[0]
+            .tell_anonymously("hello, world!")
+            .expect("Couldn't send the message.");
+    };
+    run!(asker);
+
+    // Let's wait until the blocking! and the spawn! are complete on the child side.
+    run!(blocking!({
+        std::thread::sleep(std::time::Duration::from_secs(20))
+    }));
+
+    warn!("we're done, asking bastion to stop!");
+    // We are done, stopping the bastion!
+    Bastion::stop();
+    warn!("bastion stopped!");
+    Ok(())
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+fn main() {
+    panic!("this example requires the tokio-runtime feature: `cargo run --features=tokio-runtime --example hello_tokio`")
+}
diff --git a/src/bastion/examples/message_handler_multiple_types.rs b/src/bastion/examples/message_handler_multiple_types.rs
new file mode 100644
index 00000000..44a94136
--- /dev/null
+++ b/src/bastion/examples/message_handler_multiple_types.rs
@@ -0,0 +1,62 @@
+use bastion::prelude::*;
+use std::fmt::Debug;
+use tracing::error;
+
+// This example shows that it is possible to use the MessageHandler to match
+// over different types of message.
+
+async fn child_task(ctx: BastionContext) -> Result<(), ()> {
+    loop {
+        MessageHandler::new(ctx.recv().await?)
+            .on_question(|n: i32, sender| {
+                if n == 42 {
+                    sender.reply(101).expect("Failed to reply to sender");
+                } else {
+                    error!("Expected number `42`, found `{}`", n);
+                }
+            })
+            .on_question(|s: &str, sender| {
+                if s == "marco" {
+                    sender.reply("polo").expect("Failed to reply to sender");
+                } else {
+                    panic!("Expected string `marco`, found `{}`", s);
+                }
+            })
+            .on_fallback(|v, addr| panic!("Wrong message from {:?}: got {:?}", addr, v))
+    }
+}
+
+async fn request<T: 'static + Debug + Send + Sync>(
+    child: &ChildRef,
+    body: T,
+) -> std::io::Result<()> {
+    let answer = child
+        .ask_anonymously(body)
+        .expect("Couldn't perform request")
+        .await
+        .expect("Couldn't receive answer");
+
+    MessageHandler::new(answer)
+        .on_tell(|n: i32, _| assert_eq!(n, 101))
+        .on_tell(|s: &str, _| assert_eq!(s, "polo"))
+        .on_fallback(|_, _| panic!("Unknown message"));
+
+    Ok(())
+}
+
+fn main() {
+    env_logger::init();
+
+    Bastion::init();
+    Bastion::start();
+
+    let children =
+        Bastion::children(|c| c.with_exec(child_task)).expect("Failed to spawn children");
+
+    let child = &children.elems()[0];
+
+    run!(request(child, 42)).unwrap();
+    run!(request(child, "marco")).unwrap();
+
+    // run!(request(child, "foo")).unwrap();
+}
diff --git a/src/bastion/examples/prime_numbers.rs b/src/bastion/examples/prime_numbers.rs
index 52ef2b5f..649529cd 100644
--- a/src/bastion/examples/prime_numbers.rs
+++ b/src/bastion/examples/prime_numbers.rs
@@ -52,7 +52,7 @@ mod prime_number {
         // the closing parenthesiss means it won't reach the number.
         // the maximum allowed value for maybe_prime is 9999.
         use rand::Rng;
-        let mut maybe_prime = rand::thread_rng().gen_range(min_bound, max_bound);
+        let mut maybe_prime = rand::thread_rng().gen_range(min_bound..max_bound);
         loop {
             if is_prime(maybe_prime) {
                 return number_or_panic(maybe_prime);
@@ -72,10 +72,10 @@ mod prime_number {
     fn number_or_panic(number_to_return: u128) -> u128 {
         // Let's roll a dice
         if rand::random::<u8>() % 6 == 0 {
-            panic!(format!(
+            panic!(
                 "I was about to return {} but I chose to panic instead!",
                 number_to_return
-            ))
+            )
         }
         number_to_return
     }
diff --git a/src/bastion/examples/scaling_groups.rs b/src/bastion/examples/scaling_groups.rs
index d320f12f..4fc1745b 100644
--- a/src/bastion/examples/scaling_groups.rs
+++ b/src/bastion/examples/scaling_groups.rs
@@ -26,16 +26,18 @@ fn main() {
 
 // Supervisor that tracks only the single actor with input data
 fn input_supervisor(supervisor: Supervisor) -> Supervisor {
-    supervisor.children(|children| input_group(children))
+    supervisor.children(input_group)
 }
 
 // Supervisor that tracks the actor group with rescaling in runtime.
 fn auto_resize_group_supervisor(supervisor: Supervisor) -> Supervisor {
-    supervisor.children(|children| auto_resize_group(children))
+    supervisor.children(auto_resize_group)
 }
 
+#[allow(clippy::unnecessary_mut_passed)]
 fn input_group(children: Children) -> Children {
     // we would have fully chained the children builder if it wasn't for the feature flag
+    #[allow(unused_mut)]
     let mut children = children.with_redundancy(1);
     #[cfg(feature = "scaling")]
     {
@@ -68,6 +70,7 @@ fn input_group(children: Children) -> Children {
 
 fn auto_resize_group(children: Children) -> Children {
     // we would have fully chained the children builder if it wasn't for the feature flag
+    #[allow(unused_mut)]
     let mut children = children
         .with_redundancy(3) // Start with 3 actors
         .with_heartbeat_tick(Duration::from_secs(5)); // Do heartbeat each 5 seconds
diff --git a/src/bastion/examples/tcp-servers.rs b/src/bastion/examples/tcp-servers.rs
index 60bc3a3b..a40d6734 100644
--- a/src/bastion/examples/tcp-servers.rs
+++ b/src/bastion/examples/tcp-servers.rs
@@ -3,7 +3,9 @@ use bastion::prelude::*;
 use futures::io;
 #[cfg(target_os = "windows")]
 use std::io::{self, Read, Write};
-use std::net::{TcpListener, TcpStream, ToSocketAddrs};
+#[cfg(not(target_os = "windows"))]
+use std::net::TcpListener;
+use std::net::{TcpStream, ToSocketAddrs};
 use std::sync::atomic::{AtomicUsize, Ordering};
 
 #[cfg(not(target_os = "windows"))]
@@ -19,7 +21,6 @@ async fn run(addr: impl ToSocketAddrs) -> io::Result<()> {
         // Spawn a task that echoes messages from the client back to it.
         spawn(echo(stream));
     }
-    Ok(())
 }
 
 #[cfg(target_os = "windows")]
@@ -81,7 +82,7 @@ fn main() {
                 let port = TCP_SERVERS.fetch_sub(1, Ordering::SeqCst) + 2000;
                 let addr = format!("127.0.0.1:{}", port);
 
-                run(addr);
+                run(addr).await.unwrap();
 
                 Ok(())
             })
diff --git a/src/bastion/src/README.md b/src/bastion/src/README.md
new file mode 100644
index 00000000..e1f412f3
--- /dev/null
+++ b/src/bastion/src/README.md
@@ -0,0 +1,72 @@
+Create a conference.
+
+1st Group
+Staff (5) - Going to organize the event // OK
+
+2nd Group
+Enthusiasts (50) - interested in participating to the conference (haven't registered yet) // OK
+
+3rd Group
+Attendees (empty for now) - Participate
+
+Enthusiast -> Ask one of the staff members "when is the conference going to happen ?" // OK
+Broadcast / Question => Answer 0 or 1 Staff members are going to reply eventually? // OK
+
+Staff -> Send a Leaflet to all of the enthusiasts, letting them know that they can register. // OK
+
+"hey conference <awesomeconference> is going to happen. will you be there?"
+Broadcast / Question -> if people reply with YES => fill the 3rd group
+some enthusiasts are now attendees
+
+Staff -> send the actual schedule and misc infos to Attendees
+Broadcast / Statement (Attendees)
+
+An attendee sends a thank you note to one staff member (and not bother everyone)
+One message / Statement (Staff) // OK
+
+```rust
+    let staff = Distributor::named("staff");
+
+    let enthusiasts = Distributor::named("enthusiasts");
+
+    let attendees = Disitributor::named("attendees");
+
+    // Enthusiast -> Ask the whole staff "when is the conference going to happen ?"
+    ask_one(Message + Clone) -> Result<impl Future<Output = Reply>, CouldNotSendError>
+    // await_one // await_all
+    // first ? means "have we been able to send the question?"
+    // it s in a month
+    let replies = staff.ask_one("when is the conference going to happen ?")?.await?;
+
+    ask_everyone(Message + Clone) -> Result<impl Stream<Item = Reply>, CouldNotSendError>
+    let participants = enthusiasts.ask_everyone("here's our super nice conference, it s happening people!").await?;
+
+    for participant in participants {
+        // grab the sender and add it to the attendee recipient group
+    }
+
+    // send the schedule
+    tell_everyone(Message + Clone) -> Result<(), CouldNotSendError>
+    attendees.tell_everyone("hey there, conf is in a week, here s where and how it s going to happen")?;
+
+    // send a thank you note
+    tell(Message) -> Result<(), CouldNotSendError>
+    staff.tell_one("thank's it was amazing")?;
+
+    children
+        .with_redundancy(10)
+        .with_distributor(Distributor::named("staff"))
+        // We create the function to exec when each children is called
+        .with_exec(move |ctx: BastionContext| async move { /* ... */ })
+    children
+        .with_redundancy(100)
+        .with_distributor(Distributor::named("enthusiasts"))
+        // We create the function to exec when each children is called
+        .with_exec(move |ctx: BastionContext| async move { /* ... */ })
+
+    children
+        .with_redundancy(0)
+        .with_distributor(Distributor::named("attendees"))
+        // We create the function to exec when each children is called
+        .with_exec(move |ctx: BastionContext| async move { /* ... */ })
+```
diff --git a/src/bastion/src/actor/actor_ref.rs b/src/bastion/src/actor/actor_ref.rs
new file mode 100644
index 00000000..8b7a4de5
--- /dev/null
+++ b/src/bastion/src/actor/actor_ref.rs
@@ -0,0 +1,2 @@
+#[derive(Debug, Clone)]
+pub struct ActorRef;
diff --git a/src/bastion/src/actor/context.rs b/src/bastion/src/actor/context.rs
new file mode 100644
index 00000000..baef2ed8
--- /dev/null
+++ b/src/bastion/src/actor/context.rs
@@ -0,0 +1,46 @@
+use std::sync::Arc;
+
+use async_channel::unbounded;
+
+use crate::actor::local_state::LocalState;
+use crate::actor::state::ActorState;
+use crate::mailbox::traits::TypedMessage;
+use crate::mailbox::Mailbox;
+use crate::routing::path::ActorPath;
+
+/// A structure that defines actor's state, mailbox with  
+/// messages and a local storage for user's data.
+///
+/// Each actor in Bastion has an attached context which
+/// helps to understand what is the type of actor has been
+/// launched in the system, its path, current execution state
+/// and various data that can be attached to it.
+pub struct Context {
+    /// Path to the actor in the system
+    path: Arc<ActorPath>,
+    /// Mailbox of the actor
+    //mailbox: Mailbox<TypedMessage>,
+    /// Local storage for actor's data
+    local_state: LocalState,
+    /// Current execution state of the actor
+    internal_state: ActorState,
+}
+
+impl Context {
+    // FIXME: Pass the correct system_rx instead of the fake one
+    pub(crate) fn new(path: ActorPath) -> Self {
+        //let (_system_tx, system_rx) = unbounded();
+        // let mailbox = Mailbox::new(system_rx);
+
+        let path = Arc::new(path);
+        let local_state = LocalState::new();
+        let internal_state = ActorState::new();
+
+        Context {
+            path,
+            //mailbox,
+            local_state,
+            internal_state,
+        }
+    }
+}
diff --git a/src/bastion/src/actor/definition.rs b/src/bastion/src/actor/definition.rs
new file mode 100644
index 00000000..455c5d83
--- /dev/null
+++ b/src/bastion/src/actor/definition.rs
@@ -0,0 +1,160 @@
+use std::fmt::{self, Debug, Formatter};
+use std::sync::Arc;
+
+use crate::actor::traits::Actor;
+use crate::routing::path::{ActorPath, Scope};
+
+type CustomActorNameFn = dyn Fn() -> String + Send + 'static;
+
+/// A structure that holds configuration of the Bastion actor.
+pub struct Definition {
+    /// A struct that implements actor's behaviour
+    actor: Option<Arc<dyn Actor>>,
+    /// Defines a used scope for instantiating actors.
+    scope: Scope,
+    /// Defines a function used for generating unique actor names.
+    actor_name_fn: Option<Arc<CustomActorNameFn>>,
+    /// Defines how much actors must be instantiated in the beginning.
+    redundancy: usize,
+}
+
+impl Definition {
+    /// Returns a new instance of the actor's definition.
+    pub fn new() -> Self {
+        let scope = Scope::User;
+        let actor_name_fn = None;
+        let redundancy = 1;
+        let actor = None;
+
+        Definition {
+            actor,
+            scope,
+            actor_name_fn,
+            redundancy,
+        }
+    }
+
+    /// Sets the actor to schedule.
+    pub fn actor<T: 'static>(mut self, actor: T) -> Self
+    where
+        T: Actor,
+    {
+        self.actor = Some(Arc::new(actor));
+        self
+    }
+
+    /// Overrides the default scope in which actors must be spawned
+    pub fn scope(mut self, scope: Scope) -> Self {
+        self.scope = scope;
+        self
+    }
+
+    /// Overrides the default behaviour for generating actor names
+    pub fn custom_actor_name<F>(mut self, func: F) -> Self
+    where
+        F: Fn() -> String + Send + 'static,
+    {
+        self.actor_name_fn = Some(Arc::new(func));
+        self
+    }
+
+    /// Overrides the default values for redundancy
+    pub fn redundancy(mut self, redundancy: usize) -> Self {
+        self.redundancy = match redundancy == std::usize::MIN {
+            true => redundancy.saturating_add(1),
+            false => redundancy,
+        };
+
+        self
+    }
+
+    pub(crate) fn generate_actor_path(&self) -> ActorPath {
+        match &self.actor_name_fn {
+            Some(func) => {
+                let custom_name = func();
+                ActorPath::default()
+                    .scope(self.scope.clone())
+                    .name(&custom_name)
+            }
+            None => ActorPath::default().scope(self.scope.clone()),
+        }
+    }
+}
+
+impl Debug for Definition {
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        fmt.debug_struct("Definition")
+            .field("scope", &self.scope)
+            .finish()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::actor::definition::Definition;
+    use crate::routing::path::Scope;
+
+    fn fake_actor_name() -> String {
+        let index = 1;
+        format!("Actor_{}", index)
+    }
+
+    #[test]
+    fn test_default_definition() {
+        let instance = Definition::new();
+
+        assert_eq!(instance.scope, Scope::User);
+        assert_eq!(instance.actor_name_fn.is_none(), true);
+        assert_eq!(instance.redundancy, 1);
+    }
+
+    #[test]
+    fn test_definition_with_custom_actor_name() {
+        let instance = Definition::new().custom_actor_name(fake_actor_name);
+
+        assert_eq!(instance.scope, Scope::User);
+        assert_eq!(instance.actor_name_fn.is_some(), true);
+        assert_eq!(instance.redundancy, 1);
+
+        let actor_path = instance.generate_actor_path();
+        assert_eq!(actor_path.to_string(), "bastion://node/user/Actor_1");
+        assert_eq!(actor_path.is_local(), true);
+        assert_eq!(actor_path.is_user_scope(), true);
+    }
+
+    #[test]
+    fn test_definition_with_custom_actor_name_closure() {
+        let instance = Definition::new().custom_actor_name(move || -> String {
+            let index = 1;
+            format!("Actor_{}", index)
+        });
+
+        assert_eq!(instance.scope, Scope::User);
+        assert_eq!(instance.actor_name_fn.is_some(), true);
+        assert_eq!(instance.redundancy, 1);
+
+        let actor_path = instance.generate_actor_path();
+        assert_eq!(actor_path.to_string(), "bastion://node/user/Actor_1");
+        assert_eq!(actor_path.is_local(), true);
+        assert_eq!(actor_path.is_user_scope(), true);
+    }
+
+    #[test]
+    fn test_definition_with_custom_scope_and_actor_name_closure() {
+        let instance =
+            Definition::new()
+                .scope(Scope::Temporary)
+                .custom_actor_name(move || -> String {
+                    let index = 1;
+                    format!("Actor_{}", index)
+                });
+
+        assert_eq!(instance.scope, Scope::Temporary);
+        assert_eq!(instance.actor_name_fn.is_some(), true);
+        assert_eq!(instance.redundancy, 1);
+
+        let actor_path = instance.generate_actor_path();
+        assert_eq!(actor_path.to_string(), "bastion://node/temporary/Actor_1");
+        assert_eq!(actor_path.is_temporary_scope(), true);
+    }
+}
diff --git a/src/bastion/src/actor/local_state.rs b/src/bastion/src/actor/local_state.rs
new file mode 100644
index 00000000..2311521c
--- /dev/null
+++ b/src/bastion/src/actor/local_state.rs
@@ -0,0 +1,265 @@
+/// This module contains implementation of the local state for
+/// Bastion actors. Each actor hold its own data and doesn't expose
+/// it to others, so that it will be possible to do updates in runtime
+/// without being affected by other actors or potential data races.
+use std::any::{Any, TypeId};
+use std::collections::HashMap;
+
+#[derive(Debug)]
+/// A unified storage for actor's data and intended to use
+/// only in the context of the single actor.
+pub(crate) struct LocalState {
+    table: HashMap<TypeId, LocalDataContainer>,
+}
+
+#[derive(Debug)]
+#[repr(transparent)]
+/// Transparent type for the `Box<dyn Any + Send + Sync>` type that provides
+/// simpler and easier to use API to developers.
+pub struct LocalDataContainer(Box<dyn Any + Send + Sync>);
+
+impl LocalState {
+    /// Returns a new instance of local state for actor.
+    pub(crate) fn new() -> Self {
+        LocalState {
+            table: HashMap::with_capacity(1 << 10),
+        }
+    }
+
+    /// Inserts the given value in the table. If the value
+    /// exists, it will be overridden.
+    pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) {
+        let container = LocalDataContainer::new(value);
+        self.table.insert(TypeId::of::<T>(), container);
+    }
+
+    /// Checks the given values is storing in the table.
+    pub fn contains<T: Send + Sync + 'static>(&self) -> bool {
+        self.table.contains_key(&TypeId::of::<T>())
+    }
+
+    /// Runs given closure on the immutable state
+    pub fn with_state<T, F, R>(&self, f: F) -> Option<R>
+    where
+        T: Send + Sync + 'static,
+        F: FnOnce(Option<&T>) -> Option<R>,
+    {
+        self.get_container::<T>().and_then(|e| f(e.get()))
+    }
+
+    /// Runs given closure on the mutable state
+    pub fn with_state_mut<T, F, R>(&mut self, mut f: F) -> Option<R>
+    where
+        T: Send + Sync + 'static,
+        F: FnMut(Option<&mut T>) -> Option<R>,
+    {
+        self.get_container_mut::<T>().and_then(|e| f(e.get_mut()))
+    }
+
+    /// Deletes the entry from the table.
+    pub fn remove<T: Send + Sync + 'static>(&mut self) -> bool {
+        self.table.remove(&TypeId::of::<T>()).is_some()
+    }
+
+    /// Returns immutable data to the caller.
+    pub fn get<T>(&self) -> Option<&T>
+    where
+        T: Send + Sync + 'static,
+    {
+        self.get_container::<T>().and_then(|e| e.0.downcast_ref())
+    }
+
+    /// Returns mutable data to the caller.
+    pub fn get_mut<T>(&mut self) -> Option<&mut T>
+    where
+        T: Send + Sync + 'static,
+    {
+        self.get_container_mut::<T>()
+            .and_then(|e| e.0.downcast_mut())
+    }
+
+    /// Returns immutable local data container to the caller if it exists.
+    #[inline]
+    fn get_container<T: Send + Sync + 'static>(&self) -> Option<&LocalDataContainer> {
+        self.table.get(&TypeId::of::<T>())
+    }
+
+    /// Returns mutable local data container to the caller if it exists.
+    #[inline]
+    fn get_container_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut LocalDataContainer> {
+        self.table.get_mut(&TypeId::of::<T>())
+    }
+}
+
+impl LocalDataContainer {
+    pub(crate) fn new<T: Send + Sync + 'static>(value: T) -> Self {
+        LocalDataContainer(Box::new(value))
+    }
+
+    /// Returns immutable data to the caller.
+    fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
+        self.0.downcast_ref()
+    }
+
+    /// Returns mutable data to the caller.
+    fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
+        self.0.downcast_mut()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::actor::local_state::LocalState;
+
+    #[derive(Clone, Debug, Eq, PartialEq)]
+    struct Data {
+        counter: u64,
+    }
+
+    #[test]
+    fn test_insert() {
+        let mut instance = LocalState::new();
+
+        instance.insert(Data { counter: 0 });
+        assert_eq!(instance.contains::<Data>(), true);
+    }
+
+    #[test]
+    fn test_insert_with_duplicated_data() {
+        let mut instance = LocalState::new();
+
+        instance.insert(Data { counter: 0 });
+        assert_eq!(instance.contains::<Data>(), true);
+
+        instance.insert(Data { counter: 1 });
+        assert_eq!(instance.contains::<Data>(), true);
+    }
+
+    #[test]
+    fn test_contains_returns_false() {
+        let instance = LocalState::new();
+
+        assert_eq!(instance.contains::<usize>(), false);
+    }
+
+    #[test]
+    fn test_get_container() {
+        let mut instance = LocalState::new();
+
+        let expected = Data { counter: 1 };
+
+        instance.insert(expected.clone());
+        assert_eq!(instance.contains::<Data>(), true);
+
+        let result_get = instance.get_container::<Data>();
+        assert_eq!(result_get.is_some(), true);
+
+        let container = result_get.unwrap();
+        let data = container.get::<Data>();
+        assert_eq!(data.is_some(), true);
+        assert_eq!(data.unwrap(), &expected);
+    }
+
+    #[test]
+    fn test_get_container_with_mutable_data() {
+        let mut instance = LocalState::new();
+
+        let mut expected = Data { counter: 1 };
+
+        instance.insert(expected.clone());
+        assert_eq!(instance.contains::<Data>(), true);
+
+        // Get the current snapshot of data
+        let mut data = instance.get_mut::<Data>();
+        assert_eq!(data.is_some(), true);
+        assert_eq!(data, Some(&mut expected));
+
+        data.map(|d| {
+            d.counter += 1;
+            d
+        });
+
+        // Replace the data onto new one
+        let expected_update = Data { counter: 2 };
+
+        // Check the data was updated
+        let result_updated_data = instance.get::<Data>();
+        assert_eq!(result_updated_data.is_some(), true);
+        assert_eq!(result_updated_data.unwrap(), &expected_update);
+    }
+
+    #[test]
+    fn test_immutable_run_on_state() {
+        let mut instance = LocalState::new();
+
+        let mut expected = Data { counter: 1 };
+
+        instance.insert(expected.clone());
+        assert_eq!(instance.contains::<Data>(), true);
+
+        // Get the current snapshot of data
+        let mut data: Option<Data> = instance.with_state::<Data, _, _>(|e| {
+            let mut k = e.cloned();
+            k.map(|mut e| {
+                e.counter += 1;
+                e
+            })
+        });
+        assert_eq!(data.is_some(), true);
+
+        // Expected data update
+        let expected_update = Data { counter: 2 };
+        assert_eq!(data, Some(expected_update));
+    }
+
+    #[test]
+    fn test_mutable_run_on_state() {
+        let mut instance = LocalState::new();
+
+        let mut expected = Data { counter: 1 };
+
+        instance.insert(expected.clone());
+        assert_eq!(instance.contains::<Data>(), true);
+
+        // Get the current snapshot of data
+        let mut data: Option<Data> = instance.with_state_mut::<Data, _, _>(|mut e| {
+            e.map(|mut d| {
+                d.counter += 1;
+                d
+            })
+            .cloned()
+        });
+        assert_eq!(data.is_some(), true);
+
+        // Expected data update
+        let expected_update = Data { counter: 2 };
+        assert_eq!(data, Some(expected_update));
+    }
+
+    #[test]
+    fn test_get_container_returns_none() {
+        let mut instance = LocalState::new();
+
+        let container = instance.get_container::<usize>();
+        assert_eq!(container.is_none(), true);
+    }
+
+    #[test]
+    fn test_remove_returns_true() {
+        let mut instance = LocalState::new();
+
+        instance.insert(Data { counter: 0 });
+        assert_eq!(instance.contains::<Data>(), true);
+
+        let is_removed = instance.remove::<Data>();
+        assert_eq!(is_removed, true);
+    }
+
+    #[test]
+    fn test_remove_returns_false() {
+        let mut instance = LocalState::new();
+
+        let is_removed = instance.remove::<usize>();
+        assert_eq!(is_removed, false);
+    }
+}
diff --git a/src/bastion/src/actor/mailbox.rs b/src/bastion/src/actor/mailbox.rs
new file mode 100644
index 00000000..b615a83a
--- /dev/null
+++ b/src/bastion/src/actor/mailbox.rs
@@ -0,0 +1,266 @@
+use crate::actor::actor_ref::ActorRef;
+use crate::actor::state_codes::*;
+use crate::errors::*;
+use crate::message::TypedMessage;
+use async_channel::{unbounded, Receiver, Sender};
+use lever::sync::atomics::AtomicBox;
+use std::fmt::{self, Debug, Formatter};
+use std::sync::atomic::AtomicBool;
+use std::sync::Arc;
+
+/// Struct that represents a message sender.
+#[derive(Clone)]
+pub struct MailboxTx<T>
+where
+    T: TypedMessage,
+{
+    /// Indicated the transmitter part of the actor's channel
+    /// which is using for passing messages.
+    tx: Sender<Envelope<T>>,
+    /// A field for checks that the message has been delivered to
+    /// the specific actor.
+    scheduled: Arc<AtomicBool>,
+}
+
+impl<T> MailboxTx<T>
+where
+    T: TypedMessage,
+{
+    /// Return a new instance of MailboxTx that indicates sender.
+    pub(crate) fn new(tx: Sender<Envelope<T>>) -> Self {
+        let scheduled = Arc::new(AtomicBool::new(false));
+        MailboxTx { tx, scheduled }
+    }
+
+    /// Send the message to the actor by the channel.
+    pub fn try_send(&self, msg: Envelope<T>) -> BastionResult<()> {
+        self.tx
+            .try_send(msg)
+            .map_err(|e| BError::ChanSend(e.to_string()))
+    }
+}
+
+/// A struct that holds everything related to messages that can be
+/// retrieved from other actors. Each actor holds two queues: one for
+/// messages that come from user-defined actors, and another for
+/// internal messaging that must be handled separately.
+///
+/// For each used queue, mailbox always holds the latest requested message
+/// by a user, to guarantee that the message won't be lost if something
+/// happens wrong.
+#[derive(Clone)]
+pub struct Mailbox<T>
+where
+    T: TypedMessage,
+{
+    /// User guardian sender
+    user_tx: MailboxTx<T>,
+    /// User guardian receiver
+    user_rx: Receiver<Envelope<T>>,
+    /// System guardian receiver
+    system_rx: Receiver<Envelope<T>>,
+    /// The current processing message, received from the
+    /// latest call to the user's queue
+    last_user_message: Option<Envelope<T>>,
+    /// The current processing message, received from the
+    /// latest call to the system's queue
+    last_system_message: Option<Envelope<T>>,
+    /// Mailbox state machine
+    state: Arc<AtomicBox<MailboxState>>,
+}
+
+// TODO: Add calls with recv with timeout
+impl<T> Mailbox<T>
+where
+    T: TypedMessage,
+{
+    /// Creates a new mailbox for the actor.
+    pub(crate) fn new(system_rx: Receiver<Envelope<T>>) -> Self {
+        let (tx, user_rx) = unbounded();
+        let user_tx = MailboxTx::new(tx);
+        let state = Arc::new(AtomicBox::new(MailboxState::Scheduled));
+        let last_user_message = None;
+        let last_system_message = None;
+
+        Mailbox {
+            user_tx,
+            user_rx,
+            system_rx,
+            last_user_message,
+            last_system_message,
+            state,
+        }
+    }
+
+    /// Forced receive message from user queue
+    pub async fn recv(&mut self) -> Envelope<T> {
+        let message = self
+            .user_rx
+            .recv()
+            .await
+            .map_err(|e| BError::ChanRecv(e.to_string()))
+            .unwrap();
+
+        self.last_user_message = Some(message);
+        self.last_user_message.clone().unwrap()
+    }
+
+    /// Try receiving message from user queue
+    pub async fn try_recv(&mut self) -> BastionResult<Envelope<T>> {
+        if self.last_user_message.is_some() {
+            return Err(BError::UnackedMessage);
+        }
+
+        match self.user_rx.try_recv() {
+            Ok(message) => {
+                self.last_user_message = Some(message);
+                Ok(self.last_user_message.clone().unwrap())
+            }
+            Err(e) => Err(BError::ChanRecv(e.to_string())),
+        }
+    }
+
+    /// Forced receive message from system queue
+    pub async fn sys_recv(&mut self) -> Envelope<T> {
+        let message = self
+            .system_rx
+            .recv()
+            .await
+            .map_err(|e| BError::ChanRecv(e.to_string()))
+            .unwrap();
+
+        self.last_system_message = Some(message);
+        self.last_system_message.clone().unwrap()
+    }
+
+    /// Try receiving message from system queue
+    pub async fn try_sys_recv(&mut self) -> BastionResult<Envelope<T>> {
+        if self.last_system_message.is_some() {
+            return Err(BError::UnackedMessage);
+        }
+
+        match self.system_rx.try_recv() {
+            Ok(message) => {
+                self.last_system_message = Some(message);
+                Ok(self.last_system_message.clone().unwrap())
+            }
+            Err(e) => Err(BError::ChanRecv(e.to_string())),
+        }
+    }
+
+    /// Returns the last retrieved message from the user channel
+    pub async fn get_last_user_message(&self) -> Option<Envelope<T>> {
+        self.last_user_message.clone()
+    }
+
+    /// Returns the last retrieved message from the system channel
+    pub async fn get_last_system_message(&self) -> Option<Envelope<T>> {
+        self.last_system_message.clone()
+    }
+
+    //
+    // Mailbox state machine
+    //
+    // For more information about the actor's state machine
+    // see the actor/state_codes.rs module.
+    //
+
+    pub(crate) fn set_scheduled(&self) {
+        self.state.replace_with(|_| MailboxState::Scheduled);
+    }
+
+    pub(crate) fn is_scheduled(&self) -> bool {
+        *self.state.get() == MailboxState::Scheduled
+    }
+
+    pub(crate) fn set_sent(&self) {
+        self.state.replace_with(|_| MailboxState::Sent);
+    }
+
+    pub(crate) fn is_sent(&self) -> bool {
+        *self.state.get() == MailboxState::Sent
+    }
+
+    pub(crate) fn set_awaiting(&self) {
+        self.state.replace_with(|_| MailboxState::Awaiting);
+    }
+
+    pub(crate) fn is_awaiting(&self) -> bool {
+        *self.state.get() == MailboxState::Awaiting
+    }
+}
+
+/// Struct that represents an incoming message in the actor's mailbox.
+#[derive(Clone)]
+pub struct Envelope<T>
+where
+    T: TypedMessage,
+{
+    /// The sending side of a channel. In actor's world
+    /// represented is a message sender. Can be used
+    /// for acking message when it possible.
+    sender: Option<ActorRef>,
+    /// An actual data sent by the channel
+    message: T,
+    /// Message type that helps to figure out how to deliver message
+    /// and how to ack it after the processing.
+    message_type: MessageType,
+}
+
+/// Enum that provides information what type of the message
+/// being sent through the channel.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum MessageType {
+    /// A message type that requires sending a confirmation to the
+    /// sender after begin the processing stage.
+    Ack,
+    /// A message that were broadcasted (e.g. via system dispatchers). This
+    /// message type doesn't require to be acked from the receiver's side.
+    Broadcast,
+    /// A message was sent directly and doesn't require confirmation for the
+    /// delivery and being processed.
+    Tell,
+}
+
+impl<T> Envelope<T>
+where
+    T: TypedMessage,
+{
+    /// Create a message with the given sender and inner data.
+    pub fn new(sender: Option<ActorRef>, message: T, message_type: MessageType) -> Self {
+        Envelope {
+            sender,
+            message,
+            message_type,
+        }
+    }
+
+    /// Returns a message type. Can be use for pattern matching and filtering
+    /// incoming message from other actors.
+    pub fn message_type(&self) -> MessageType {
+        self.message_type.clone()
+    }
+
+    /// Sends a confirmation to the message sender.
+    pub(crate) async fn ack(&self) {
+        match self.message_type {
+            MessageType::Ack => unimplemented!(),
+            MessageType::Broadcast => unimplemented!(),
+            MessageType::Tell => unimplemented!(),
+        }
+    }
+}
+
+impl<T> Debug for Envelope<T>
+where
+    T: TypedMessage,
+{
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        fmt.debug_struct("Message")
+            .field("message", &self.message)
+            .field("message_type", &self.message_type)
+            .finish()
+    }
+}
+
+// TODO: Add tests
diff --git a/src/bastion/src/actor/mod.rs b/src/bastion/src/actor/mod.rs
new file mode 100644
index 00000000..8410474b
--- /dev/null
+++ b/src/bastion/src/actor/mod.rs
@@ -0,0 +1,6 @@
+pub mod actor_ref;
+pub mod context;
+pub mod definition;
+pub mod local_state;
+pub mod state;
+pub mod traits;
diff --git a/src/bastion/src/actor/state.rs b/src/bastion/src/actor/state.rs
new file mode 100644
index 00000000..0b6f6e61
--- /dev/null
+++ b/src/bastion/src/actor/state.rs
@@ -0,0 +1,274 @@
+/// Module that holds state machine implementation for the Bastion actor.
+/// Not available for changes for crate users, but used internally for clean
+/// actor's state transitions in the readable and the debuggable manner.
+///
+/// The whole state machine of the actor can be represented by the
+/// following schema:
+/// ```ignore
+///                            +---> Stopped ----+
+///                            |                 |
+///                            |                 |
+/// Init -> Sync -> Scheduled -+---> Terminated -+---> Deinit -> Removed
+///                  ↑     |   |                 |
+///                  |     ↓   |                 |
+///                 Awaiting   +---> Failed -----+
+///                            |                 |
+///                            |                 |
+///                            +---> Finished ---+
+///
+/// ```
+/// The transitions between the states is called by the actor's context
+/// internally and aren't available to use and override by crate users.
+///
+use crossbeam::atomic::AtomicCell;
+
+// Actor state holder
+#[derive(Debug)]
+pub(crate) struct ActorState {
+    inner: AtomicCell<InnerState>,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+enum InnerState {
+    /// The first state for actors. This state is the initial point after
+    /// being created or added to the Bastion node in runtime. At this stage,
+    /// actor isn't doing any useful job and retrieving any messages from other
+    /// parts of the cluster yet.
+    /// However, it can do some initialization steps (e.g. register itself
+    /// in dispatchers or adding the initial data to the local state),
+    /// before being available to the rest of the cluster.
+    Init,
+    /// An intermediate state that used for sychronization purposes. Useful
+    /// for cases when necessary to have a consensus between multiple actors.
+    Sync,
+    /// The main state in which actor can stay for indefinite amount of time.
+    /// During this state, actor does useful work (e.g. processing the incoming
+    /// messages from other actors) that doesn't require any asynchronous calls.
+    Scheduled,
+    /// Special kind of the actor's state that helps to understand that actor
+    /// is awaiting for other futures (e.g. I/O, network) or awaiting a response
+    /// from other actor in the Bastion cluster.
+    Awaiting,
+    /// Actor has been stopped by the system or a user's call.
+    Stopped,
+    /// Actor has been terminated by the system or a user's call.
+    Terminated,
+    /// Actor has been stopped because of a raised panic during the execution
+    /// or returned an error.
+    Failed,
+    /// Actor has completed code execution with the success.
+    Finished,
+    /// The deinitialization state for the actor. During this stage the actor
+    /// must unregister itself from the node, used dispatchers and any other
+    /// parts where was initialized in the beginning. Can contain an additional
+    /// user logic before being removed from the cluster.
+    Deinit,
+    /// The final state of the actor. The actor can be removed gracefully from
+    /// the Bastion node, without any negative impact to the cluster.
+    Removed,
+}
+
+impl ActorState {
+    pub(crate) fn new() -> Self {
+        ActorState {
+            inner: AtomicCell::new(InnerState::Init),
+        }
+    }
+
+    pub(crate) fn set_sync(&self) {
+        self.inner.store(InnerState::Sync);
+    }
+
+    pub(crate) fn set_scheduled(&self) {
+        self.inner.store(InnerState::Scheduled);
+    }
+
+    pub(crate) fn set_awaiting(&self) {
+        self.inner.store(InnerState::Awaiting);
+    }
+
+    pub(crate) fn set_stopped(&self) {
+        self.inner.store(InnerState::Stopped);
+    }
+
+    pub(crate) fn set_terminated(&self) {
+        self.inner.store(InnerState::Terminated);
+    }
+
+    pub(crate) fn set_failed(&self) {
+        self.inner.store(InnerState::Failed);
+    }
+
+    pub(crate) fn set_finished(&self) {
+        self.inner.store(InnerState::Finished);
+    }
+
+    pub(crate) fn set_deinit(&self) {
+        self.inner.store(InnerState::Deinit);
+    }
+
+    pub(crate) fn set_removed(&self) {
+        self.inner.store(InnerState::Removed);
+    }
+
+    pub(crate) fn is_init(&self) -> bool {
+        self.inner.load() == InnerState::Init
+    }
+
+    pub(crate) fn is_sync(&self) -> bool {
+        self.inner.load() == InnerState::Sync
+    }
+
+    pub(crate) fn is_scheduled(&self) -> bool {
+        self.inner.load() == InnerState::Scheduled
+    }
+
+    pub(crate) fn is_awaiting(&self) -> bool {
+        self.inner.load() == InnerState::Awaiting
+    }
+
+    pub(crate) fn is_stopped(&self) -> bool {
+        self.inner.load() == InnerState::Stopped
+    }
+
+    pub(crate) fn is_terminated(&self) -> bool {
+        self.inner.load() == InnerState::Terminated
+    }
+
+    pub(crate) fn is_failed(&self) -> bool {
+        self.inner.load() == InnerState::Failed
+    }
+
+    pub(crate) fn is_finished(&self) -> bool {
+        self.inner.load() == InnerState::Finished
+    }
+
+    pub(crate) fn is_deinit(&self) -> bool {
+        self.inner.load() == InnerState::Deinit
+    }
+
+    pub(crate) fn is_removed(&self) -> bool {
+        self.inner.load() == InnerState::Removed
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::actor::state::ActorState;
+
+    #[test]
+    fn test_happy_path() {
+        let state = ActorState::new();
+
+        assert_eq!(state.is_init(), true);
+
+        state.set_sync();
+        assert_eq!(state.is_sync(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_finished();
+        assert_eq!(state.is_finished(), true);
+
+        state.set_deinit();
+        assert_eq!(state.is_deinit(), true);
+
+        state.set_removed();
+        assert_eq!(state.is_removed(), true);
+    }
+
+    #[test]
+    fn test_happy_path_with_awaiting_state() {
+        let state = ActorState::new();
+
+        assert_eq!(state.is_init(), true);
+
+        state.set_sync();
+        assert_eq!(state.is_sync(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_awaiting();
+        assert_eq!(state.is_awaiting(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_finished();
+        assert_eq!(state.is_finished(), true);
+
+        state.set_deinit();
+        assert_eq!(state.is_deinit(), true);
+
+        state.set_removed();
+        assert_eq!(state.is_removed(), true);
+    }
+
+    #[test]
+    fn test_path_with_stopped_state() {
+        let state = ActorState::new();
+
+        assert_eq!(state.is_init(), true);
+
+        state.set_sync();
+        assert_eq!(state.is_sync(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_stopped();
+        assert_eq!(state.is_stopped(), true);
+
+        state.set_deinit();
+        assert_eq!(state.is_deinit(), true);
+
+        state.set_removed();
+        assert_eq!(state.is_removed(), true);
+    }
+
+    #[test]
+    fn test_path_with_terminated_state() {
+        let state = ActorState::new();
+
+        assert_eq!(state.is_init(), true);
+
+        state.set_sync();
+        assert_eq!(state.is_sync(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_terminated();
+        assert_eq!(state.is_terminated(), true);
+
+        state.set_deinit();
+        assert_eq!(state.is_deinit(), true);
+
+        state.set_removed();
+        assert_eq!(state.is_removed(), true);
+    }
+
+    #[test]
+    fn test_path_with_failed_state() {
+        let state = ActorState::new();
+
+        assert_eq!(state.is_init(), true);
+
+        state.set_sync();
+        assert_eq!(state.is_sync(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_failed();
+        assert_eq!(state.is_failed(), true);
+
+        state.set_deinit();
+        assert_eq!(state.is_deinit(), true);
+
+        state.set_removed();
+        assert_eq!(state.is_removed(), true);
+    }
+}
diff --git a/src/bastion/src/actor/state_codes.rs b/src/bastion/src/actor/state_codes.rs
new file mode 100644
index 00000000..32bc1221
--- /dev/null
+++ b/src/bastion/src/actor/state_codes.rs
@@ -0,0 +1,78 @@
+#[derive(PartialEq, PartialOrd)]
+/// An enum that specifies a lifecycle of the message that has
+/// been sent by the actor in the system.
+///
+/// The whole lifecycle of the message can be described by the
+/// next schema:
+///
+///    +------ Message processed ----+
+///    ↓                             |
+/// Scheduled -> Sent -> Awaiting ---+
+///               ↑           |   
+///               +-- Retry --+
+///
+pub(crate) enum MailboxState {
+    /// Mailbox has been scheduled
+    Scheduled,
+    /// Message has been sent to destination
+    Sent,
+    /// Ack has currently been awaited
+    Awaiting,
+}
+
+#[derive(PartialEq, PartialOrd)]
+/// Special kind of enum that describes possible states of
+/// the actor in the system.  
+///
+/// The whole state machine of the actor can be represented by
+/// the following schema:
+///````ignore
+///                            +---> Stopped ----+
+///                            |                 |
+///                            |                 |
+/// Init -> Sync -> Scheduled -+---> Terminated -+---> Deinit -> Removed
+///                  ↑     |   |                 |
+///                  |     ↓   |                 |
+///                 Awaiting   +---> Failed -----+
+///                            |                 |
+///                            |                 |
+///                            +---> Finished ---+
+///```
+pub(crate) enum ActorState {
+    /// The first state for actors. This state is the initial point
+    /// after being created or added to the Bastion node in runtime.
+    /// At this stage, actor isn't doing any useful job and retrieving
+    /// any messages from other parts of the cluster yet.
+    /// However, it can do some initialization steps (e.g. register itself
+    /// in dispatchers or adding the initial data to the local state),
+    /// before being available to the rest of the cluster.
+    Init,
+    /// Remote or local state synchronization. this behaves like a half state
+    /// to converging consensus between multiple actor states.
+    Sync,
+    /// The main state in which actor can stay for indefinite amount of time.
+    /// During this state, actor doing useful work (e.g. processing the incoming
+    /// message from other actors) that doesn't require any asynchronous calls.
+    Scheduled,
+    /// Special kind of the scheduled state which help to understand that
+    /// actor is awaiting for other futures or response messages from other
+    /// actors in the Bastion cluster.
+    Awaiting,
+    /// Actor has been stopped by the system or a user's call.
+    Stopped,
+    /// Actor has been terminated by the system or a user's call.
+    Terminated,
+    /// Actor has stopped doing any useful work because of a raised panic
+    /// or user's error during the execution.
+    Failed,
+    /// Actor has completed an execution with the success.
+    Finished,
+    /// The deinitialization state for the actor. During this stage the actor
+    /// must unregister itself from the node, used dispatchers and any other
+    /// parts where was initialized in the beginning. Can contain an additional
+    /// user logic before being removed from the cluster.
+    Deinit,
+    /// The final state of the actor. The actor can be removed
+    /// gracefully from the node, because is not available anymore.
+    Removed,
+}
diff --git a/src/bastion/src/actor/traits.rs b/src/bastion/src/actor/traits.rs
new file mode 100644
index 00000000..2ac440d9
--- /dev/null
+++ b/src/bastion/src/actor/traits.rs
@@ -0,0 +1,16 @@
+use async_trait::async_trait;
+
+use crate::actor::context::Context;
+use crate::errors::BastionResult;
+
+#[async_trait]
+pub trait Actor: Sync {
+    async fn on_init(&self, _ctx: &mut Context) {}
+    async fn on_sync(&self, _ctx: &mut Context) {}
+    async fn on_stopped(&self, _ctx: &mut Context) {}
+    async fn on_terminated(&self, _ctx: &mut Context) {}
+    async fn on_failed(&self, _ctx: &mut Context) {}
+    async fn on_finished(&self, _ctx: &mut Context) {}
+    async fn on_deinit(&self, _ctx: &mut Context) {}
+    async fn handler(&self, ctx: &mut Context) -> BastionResult<()>;
+}
diff --git a/src/bastion/src/bastion.rs b/src/bastion/src/bastion.rs
index af6f231b..b32122f3 100644
--- a/src/bastion/src/bastion.rs
+++ b/src/bastion/src/bastion.rs
@@ -4,10 +4,10 @@ use crate::children_ref::ChildrenRef;
 use crate::config::Config;
 use crate::context::{BastionContext, BastionId};
 use crate::envelope::Envelope;
+use crate::global_system::SYSTEM;
 use crate::message::{BastionMessage, Message};
 use crate::path::BastionPathElement;
 use crate::supervisor::{Supervisor, SupervisorRef};
-use crate::system::SYSTEM;
 
 use core::future::Future;
 use tracing::{debug, trace};
@@ -29,7 +29,18 @@ distributed_api! {
 /// ```rust
 /// use bastion::prelude::*;
 ///
-/// fn main() {
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// fn run() {
 ///     /// Creating the system's configuration...
 ///     let config = Config::new().hide_backtraces();
 ///     // ...and initializing the system with it (this is required)...
@@ -172,6 +183,18 @@ impl Bastion {
     /// # Example
     ///
     /// ```rust
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// use bastion::prelude::*;
     ///
     /// Bastion::init();
@@ -181,10 +204,8 @@ impl Bastion {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Config`]: struct.Config.html
-    /// [`Bastion::init_with`]: #method.init_with
     pub fn init() {
         let config = Config::default();
         Bastion::init_with(config)
@@ -206,6 +227,18 @@ impl Bastion {
     /// ```rust
     /// use bastion::prelude::*;
     ///
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// let config = Config::new()
     ///     .show_backtraces();
     ///
@@ -216,10 +249,8 @@ impl Bastion {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Config`]: struct.Config.html
-    /// [`Bastion::init`]: #method.init
     pub fn init_with(config: Config) {
         debug!("Bastion: Initializing with config: {:?}", config);
         if config.backtraces().is_hide() {
@@ -227,7 +258,7 @@ impl Bastion {
             std::panic::set_hook(Box::new(|_| ()));
         }
 
-        lazy_static::initialize(&SYSTEM);
+        let _ = &SYSTEM;
     }
 
     /// Creates a new [`Supervisor`], passes it through the specified
@@ -248,6 +279,18 @@ impl Bastion {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// let sp_ref: SupervisorRef = Bastion::supervisor(|sp| {
@@ -259,10 +302,8 @@ impl Bastion {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Supervisor`]: supervisor/struct.Supervisor.html
-    /// [`SupervisorRef`]: supervisor/struct.SupervisorRef.html
     pub fn supervisor<S>(init: S) -> Result<SupervisorRef, ()>
     where
         S: FnOnce(Supervisor) -> Supervisor,
@@ -307,6 +348,18 @@ impl Bastion {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// let children_ref: ChildrenRef = Bastion::children(|children| {
@@ -328,10 +381,8 @@ impl Bastion {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Children`]: children/struct.Children.html
-    /// [`ChildrenRef`]: children/struct.ChildrenRef.html
     pub fn children<C>(init: C) -> Result<ChildrenRef, ()>
     where
         C: FnOnce(Children) -> Children,
@@ -357,6 +408,18 @@ impl Bastion {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// let children_ref: ChildrenRef = Bastion::spawn(|ctx: BastionContext| {
@@ -369,12 +432,8 @@ impl Bastion {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Children::with_exec`]: children/struct.Children.html#method.with_exec
-    /// [`Bastion::children`]: #method.children
-    /// [`Children`]: children/struct.Children.html
-    /// [`ChildrenRef`]: children/struct.ChildrenRef.html
     pub fn spawn<I, F>(action: I) -> Result<ChildrenRef, ()>
     where
         I: Fn(BastionContext) -> F + Send + 'static,
@@ -410,7 +469,18 @@ impl Bastion {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     /// let msg = "A message containing data.";
@@ -437,7 +507,7 @@ impl Bastion {
     ///     # Bastion::start();
     ///     # Bastion::stop();
     ///     # Bastion::block_until_stopped();
-    /// # }
+    /// # }    
     /// ```
     pub fn broadcast<M: Message>(msg: M) -> Result<(), M> {
         debug!("Bastion: Broadcasting message: {:?}", msg);
@@ -459,6 +529,18 @@ impl Bastion {
     /// ```rust
     /// use bastion::prelude::*;
     ///
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// Bastion::init();
     ///
     /// // Use bastion, spawn children and supervisors...
@@ -470,6 +552,7 @@ impl Bastion {
     /// #
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn start() {
         debug!("Bastion: Starting.");
@@ -488,6 +571,19 @@ impl Bastion {
     /// ```rust
     /// use bastion::prelude::*;
     ///
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    ///
     /// Bastion::init();
     ///
     /// // Use bastion, spawn children and supervisors...
@@ -499,6 +595,7 @@ impl Bastion {
     ///
     /// Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn stop() {
         debug!("Bastion: Stopping.");
@@ -517,6 +614,18 @@ impl Bastion {
     /// ```rust
     /// use bastion::prelude::*;
     ///
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// Bastion::init();
     ///
     /// // Use bastion, spawn children and supervisors...
@@ -527,6 +636,7 @@ impl Bastion {
     ///
     /// Bastion::kill();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn kill() {
         debug!("Bastion: Killing.");
@@ -547,12 +657,24 @@ impl Bastion {
     }
 
     /// Blocks the current thread until the system is stopped
-    /// (either by calling [`Bastion::stop()`] or
+    /// (either by calling [`Bastion::stop`] or
     /// [`Bastion::kill`]).
     ///
     /// # Example
     ///
     /// ```rust
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// use bastion::prelude::*;
     ///
     /// Bastion::init();
@@ -567,10 +689,8 @@ impl Bastion {
     /// Bastion::block_until_stopped();
     /// // The system is now stopped. A child might have
     /// // stopped or killed it...
+    /// # }
     /// ```
-    ///
-    /// [`Bastion::stop()`]: #method.stop
-    /// [`Bastion::kill()`]: #method.kill
     pub fn block_until_stopped() {
         debug!("Bastion: Blocking until system is stopped.");
         SYSTEM.wait_until_stopped();
diff --git a/src/bastion/src/broadcast.rs b/src/bastion/src/broadcast.rs
index 893eccb4..fc73cba2 100644
--- a/src/bastion/src/broadcast.rs
+++ b/src/bastion/src/broadcast.rs
@@ -1,10 +1,10 @@
 use crate::children_ref::ChildrenRef;
 use crate::context::BastionId;
 use crate::envelope::Envelope;
+use crate::global_system::SYSTEM;
 use crate::message::BastionMessage;
 use crate::path::{BastionPath, BastionPathElement};
 use crate::supervisor::SupervisorRef;
-use crate::system::SYSTEM;
 use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
 use futures::prelude::*;
 use fxhash::FxHashMap;
diff --git a/src/bastion/src/callbacks.rs b/src/bastion/src/callbacks.rs
index 0c271b96..293c7c54 100644
--- a/src/bastion/src/callbacks.rs
+++ b/src/bastion/src/callbacks.rs
@@ -8,6 +8,7 @@ pub(crate) enum CallbackType {
     AfterStop,
     BeforeRestart,
     BeforeStart,
+    AfterStart,
 }
 
 #[derive(Default, Clone)]
@@ -19,6 +20,18 @@ pub(crate) enum CallbackType {
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 /// Bastion::children(|children| {
@@ -41,12 +54,14 @@ pub(crate) enum CallbackType {
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 ///
-/// [`Supervisor`]: supervisor/struct.Supervisor.html
-/// [`Children`]: children/struct.Children.html
+/// [`Supervisor`]: crate::supervisor::Supervisor
+/// [`Children`]: crate::children::Children
 pub struct Callbacks {
     before_start: Option<Arc<dyn Fn() + Send + Sync>>,
+    after_start: Option<Arc<dyn Fn() + Send + Sync>>,
     before_restart: Option<Arc<dyn Fn() + Send + Sync>>,
     after_restart: Option<Arc<dyn Fn() + Send + Sync>>,
     after_stop: Option<Arc<dyn Fn() + Send + Sync>>,
@@ -61,6 +76,18 @@ impl Callbacks {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -83,10 +110,11 @@ impl Callbacks {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`Supervisor::with_callbacks`]: supervisor/struct.Supervisor.html#method.with_callbacks
-    /// [`Children::with_callbacks`]: children/struct.Children.html#method.with_callbacks
+    /// [`Supervisor::with_callbacks`]: crate::supervisor::Supervisor::with_callbacks
+    /// [`Children::with_callbacks`]: crate::children::Children::with_callbacks
     pub fn new() -> Self {
         Callbacks::default()
     }
@@ -107,6 +135,18 @@ impl Callbacks {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|supervisor| {
@@ -138,11 +178,12 @@ impl Callbacks {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`Supervisor`]: supervisor/struct.Supervisor.html
-    /// [`Children`]: children/struct.Children.html
-    /// [`with_after_restart`]: #method.with_after_start
+    /// [`Supervisor`]: crate::supervisor::Supervisor
+    /// [`Children`]: crate::children::Children
+    /// [`with_after_restart`]: Self::with_after_restart
     pub fn with_before_start<C>(mut self, before_start: C) -> Self
     where
         C: Fn() + Send + Sync + 'static,
@@ -152,6 +193,74 @@ impl Callbacks {
         self
     }
 
+    /// Sets the method that will get called right after the [`Supervisor`]
+    /// or [`Children`] is launched.
+    /// This method will be called after the child has subscribed to its distributors and dispatchers.
+    ///
+    /// Once the callback has run, the child has caught up it's message backlog,
+    /// and is waiting for new messages to process.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// #
+    /// # Bastion::supervisor(|supervisor| {
+    /// supervisor.children(|children| {
+    ///     let callbacks = Callbacks::new()
+    ///         .with_after_start(|| println!("Children group ready to process messages."));
+    ///
+    ///     children
+    ///         .with_exec(|ctx| {
+    ///             // -- Children group started.
+    ///             // with_after_start called
+    ///             async move {
+    ///                 // ...
+    ///
+    ///                 // This will stop the children group...
+    ///                 Ok(())
+    ///                 // Note that because the children group stopped by itself,
+    ///                 // if its supervisor restarts it, its `before_start` callback
+    ///                 // will get called and not `after_restart`.
+    ///             }
+    ///             // -- Children group stopped.
+    ///         })
+    ///         .with_callbacks(callbacks)
+    /// })
+    /// # }).unwrap();
+    /// #
+    /// # Bastion::start();
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    ///
+    /// [`Supervisor`]: crate::supervisor::Supervisor
+    /// [`Children`]: crate::children::Children
+    /// [`with_after_restart`]: Self::with_after_restart
+    pub fn with_after_start<C>(mut self, after_start: C) -> Self
+    where
+        C: Fn() + Send + Sync + 'static,
+    {
+        let after_start = Arc::new(after_start);
+        self.after_start = Some(after_start);
+        self
+    }
+
     /// Sets the method that will get called before the [`Supervisor`]
     /// or [`Children`] is reset if:
     /// - the supervisor of the supervised element using this callback
@@ -166,6 +275,18 @@ impl Callbacks {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|supervisor| {
@@ -199,11 +320,12 @@ impl Callbacks {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`Supervisor`]: supervisor/struct.Supervisor.html
-    /// [`Children`]: children/struct.Children.html
-    /// [`with_after_stop`]: #method.with_after_stop
+    /// [`Supervisor`]: crate::supervisor::Supervisor
+    /// [`Children`]: crate::children::Children
+    /// [`with_after_stop`]: Self::with_after_stop
     pub fn with_before_restart<C>(mut self, before_restart: C) -> Self
     where
         C: Fn() + Send + Sync + 'static,
@@ -227,6 +349,18 @@ impl Callbacks {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|supervisor| {
@@ -260,11 +394,12 @@ impl Callbacks {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`Supervisor`]: supervisor/struct.Supervisor.html
-    /// [`Children`]: children/struct.Children.html
-    /// [`with_before_start`]: #method.with_before_start
+    /// [`Supervisor`]: crate::supervisor::Supervisor
+    /// [`Children`]: crate::children::Children
+    /// [`with_before_start`]: Self::method.with_before_start
     pub fn with_after_restart<C>(mut self, after_restart: C) -> Self
     where
         C: Fn() + Send + Sync + 'static,
@@ -292,6 +427,18 @@ impl Callbacks {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|supervisor| {
@@ -323,11 +470,12 @@ impl Callbacks {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`Supervisor`]: supervisor/struct.Supervisor.html
-    /// [`Children`]: children/struct.Children.html
-    /// [`with_before_restart`]: #method.with_before_restart
+    /// [`Supervisor`]: crate::supervisor::Supervisor
+    /// [`Children`]: crate::children::Children
+    /// [`with_before_restart`]: Self::with_before_restart
     pub fn with_after_stop<C>(mut self, after_stop: C) -> Self
     where
         C: Fn() + Send + Sync + 'static,
@@ -350,7 +498,7 @@ impl Callbacks {
     /// assert!(callbacks.has_before_start());
     /// ```
     ///
-    /// [`with_before_start`]: #method.with_before_start
+    /// [`with_before_start`]: Self::with_before_start
     pub fn has_before_start(&self) -> bool {
         self.before_start.is_some()
     }
@@ -368,7 +516,7 @@ impl Callbacks {
     /// assert!(callbacks.has_before_restart());
     /// ```
     ///
-    /// [`with_before_restart`]: #method.with_before_restart
+    /// [`with_before_restart`]: Self::with_before_restart
     pub fn has_before_restart(&self) -> bool {
         self.before_restart.is_some()
     }
@@ -386,7 +534,7 @@ impl Callbacks {
     /// assert!(callbacks.has_after_restart());
     /// ```
     ///
-    /// [`with_after_restart`]: #method.with_after_restart
+    /// [`with_after_restart`]: Self::with_after_restart
     pub fn has_after_restart(&self) -> bool {
         self.after_restart.is_some()
     }
@@ -404,7 +552,7 @@ impl Callbacks {
     /// assert!(callbacks.has_after_stop());
     /// ```
     ///
-    /// [`with_after_stop`]: #method.with_after_stop
+    /// [`with_after_stop`]: Self::with_after_stop
     pub fn has_after_stop(&self) -> bool {
         self.after_stop.is_some()
     }
@@ -415,6 +563,12 @@ impl Callbacks {
         }
     }
 
+    pub(crate) fn after_start(&self) {
+        if let Some(after_start) = &self.after_start {
+            after_start()
+        }
+    }
+
     pub(crate) fn before_restart(&self) {
         if let Some(before_restart) = &self.before_restart {
             before_restart()
diff --git a/src/bastion/src/child.rs b/src/bastion/src/child.rs
index b4eca127..ac380ca7 100644
--- a/src/bastion/src/child.rs
+++ b/src/bastion/src/child.rs
@@ -5,12 +5,12 @@ use crate::callbacks::{CallbackType, Callbacks};
 use crate::child_ref::ChildRef;
 use crate::context::{BastionContext, BastionId, ContextState};
 use crate::envelope::Envelope;
+use crate::global_system::SYSTEM;
 use crate::message::BastionMessage;
 #[cfg(feature = "scaling")]
 use crate::resizer::ActorGroupStats;
-use crate::system::SYSTEM;
 use anyhow::Result as AnyResult;
-use async_mutex::Mutex;
+
 use bastion_executor::pool;
 use futures::pending;
 use futures::poll;
@@ -35,11 +35,11 @@ pub(crate) struct Child {
     callbacks: Callbacks,
     // The future that this child is executing.
     exec: Exec,
-    // A lock behind which is the child's context state.
+    // The child's context state.
     // This is used to store the messages that were received
     // for the child's associated future to be able to
     // retrieve them.
-    state: Arc<Mutex<Pin<Box<ContextState>>>>,
+    state: Arc<Pin<Box<ContextState>>>,
     // Messages that were received before the child was
     // started. Those will be "replayed" once a start message
     // is received.
@@ -71,7 +71,7 @@ impl Child {
         exec: Exec,
         callbacks: Callbacks,
         bcast: Broadcast,
-        state: Arc<Mutex<Pin<Box<ContextState>>>>,
+        state: Arc<Pin<Box<ContextState>>>,
         child_ref: ChildRef,
     ) -> Self {
         debug!("Child({}): Initializing.", bcast.id());
@@ -125,12 +125,14 @@ impl Child {
     fn stopped(&mut self) {
         debug!("Child({}): Stopped.", self.id());
         self.remove_from_dispatchers();
+        let _ = self.remove_from_distributors();
         self.bcast.stopped();
     }
 
     fn faulted(&mut self) {
         debug!("Child({}): Faulted.", self.id());
         self.remove_from_dispatchers();
+        let _ = self.remove_from_distributors();
 
         let parent = self.bcast.parent().clone().into_children().unwrap();
         let path = self.bcast.path().clone();
@@ -200,9 +202,7 @@ impl Child {
                 sign,
             } => {
                 debug!("Child({}): Received a message: {:?}", self.id(), msg);
-                let state = self.state.clone();
-                let mut guard = state.lock().await;
-                guard.push_message(msg, sign);
+                self.state.push_message(msg, sign);
             }
             Envelope {
                 msg: BastionMessage::RestartRequired { .. },
@@ -283,22 +283,22 @@ impl Child {
             CallbackType::BeforeRestart => self.callbacks.before_restart(),
             CallbackType::AfterRestart => self.callbacks.after_restart(),
             CallbackType::AfterStop => self.callbacks.after_stop(),
+            CallbackType::AfterStart => self.callbacks.after_start(),
         }
     }
 
     #[cfg(feature = "scaling")]
     async fn update_stats(&mut self) {
-        let guard = self.state.lock().await;
-        let context_state = guard.as_ref();
-        let storage = guard.stats();
+        let mailbox_size = self.state.mailbox_size();
+        let storage = self.state.stats();
 
         let mut stats = ActorGroupStats::load(storage.clone());
-        stats.update_average_mailbox_size(context_state.mailbox_size());
+        stats.update_average_mailbox_size(mailbox_size);
         stats.store(storage);
 
-        let actor_stats_table = guard.actor_stats();
+        let actor_stats_table = self.state.actor_stats();
         actor_stats_table
-            .insert(self.bcast.id().clone(), context_state.mailbox_size())
+            .insert(self.bcast.id().clone(), mailbox_size)
             .ok();
     }
 
@@ -308,6 +308,12 @@ impl Child {
             error!("couldn't add actor to the registry: {}", e);
             return;
         };
+        if let Err(e) = self.register_to_distributors() {
+            error!("couldn't add actor to the distributors: {}", e);
+            return;
+        };
+
+        self.callbacks.after_start();
 
         loop {
             #[cfg(feature = "scaling")]
@@ -403,6 +409,35 @@ impl Child {
         Ok(())
     }
 
+    /// Adds the actor into each distributor declared in the parent node.
+    fn register_to_distributors(&self) -> AnyResult<()> {
+        if let Some(parent) = self.bcast.parent().clone().into_children() {
+            let child_ref = self.child_ref.clone();
+            let distributors = parent.distributors();
+
+            let global_dispatcher = SYSTEM.dispatcher();
+            distributors
+                .iter()
+                .map(|&distributor| {
+                    global_dispatcher.register_recipient(&distributor, child_ref.clone())
+                })
+                .collect::<AnyResult<Vec<_>>>()?;
+        }
+        Ok(())
+    }
+
+    /// Cleanup the actor's record from each declared distributor.
+    fn remove_from_distributors(&self) -> AnyResult<()> {
+        if let Some(parent) = self.bcast.parent().clone().into_children() {
+            let child_ref = self.child_ref.clone();
+            let distributors = parent.distributors();
+
+            let global_dispatcher = SYSTEM.dispatcher();
+            global_dispatcher.remove_recipient(distributors, child_ref)?;
+        }
+        Ok(())
+    }
+
     /// Cleanup the actor's record from each declared dispatcher.
     fn remove_from_dispatchers(&self) {
         if let Some(parent) = self.bcast.parent().clone().into_children() {
@@ -416,9 +451,10 @@ impl Child {
 
     #[cfg(feature = "scaling")]
     async fn cleanup_actors_stats(&mut self) {
-        let guard = self.state.lock().await;
-        let actor_stats_table = guard.actor_stats();
-        actor_stats_table.remove(&self.bcast.id().clone()).ok();
+        self.state
+            .actor_stats()
+            .remove(&self.bcast.id().clone())
+            .ok();
     }
 }
 
diff --git a/src/bastion/src/child_ref.rs b/src/bastion/src/child_ref.rs
index 139c830c..7cd90e7e 100644
--- a/src/bastion/src/child_ref.rs
+++ b/src/bastion/src/child_ref.rs
@@ -1,10 +1,10 @@
 //!
 //! Allows users to communicate with Child through the mailboxes.
-use crate::broadcast::Sender;
 use crate::context::BastionId;
 use crate::envelope::{Envelope, RefAddr};
 use crate::message::{Answer, BastionMessage, Message};
 use crate::path::BastionPath;
+use crate::{broadcast::Sender, prelude::SendError};
 use std::cmp::{Eq, PartialEq};
 use std::fmt::Debug;
 use std::hash::{Hash, Hasher};
@@ -67,6 +67,18 @@ impl ChildRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -82,6 +94,7 @@ impl ChildRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn id(&self) -> &BastionId {
         &self.id
@@ -98,6 +111,18 @@ impl ChildRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -114,6 +139,7 @@ impl ChildRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn is_public(&self) -> bool {
         self.is_public
@@ -135,7 +161,18 @@ impl ChildRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     /// // The message that will be "told"...
     /// const TELL_MSG: &'static str = "A message containing data (tell).";
@@ -178,6 +215,75 @@ impl ChildRef {
         self.send(env).map_err(|env| env.into_msg().unwrap())
     }
 
+    /// Try to send a message to the child this `ChildRef` is referencing.
+    /// This message is intended to be used outside of Bastion context when
+    /// there is no way for receiver to identify message sender
+    ///
+    /// This method returns `()` if it succeeded, or a `SendError`(../child_ref/enum.SendError.html)
+    /// otherwise.
+    ///
+    /// # Argument
+    ///
+    /// * `msg` - The message to send.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    ///     # Bastion::init();
+    /// // The message that will be "told"...
+    /// const TELL_MSG: &'static str = "A message containing data (tell).";
+    ///
+    ///     # let children_ref =
+    /// // Create a new child...
+    /// Bastion::children(|children| {
+    ///     children.with_exec(|ctx: BastionContext| {
+    ///         async move {
+    ///             // ...which will receive the message "told"...
+    ///             msg! { ctx.recv().await?,
+    ///                 msg: &'static str => {
+    ///                     assert_eq!(msg, TELL_MSG);
+    ///                     // Handle the message...
+    ///                 };
+    ///                 // This won't happen because this example
+    ///                 // only "tells" a `&'static str`...
+    ///                 _: _ => ();
+    ///             }
+    ///
+    ///             Ok(())
+    ///         }
+    ///     })
+    /// }).expect("Couldn't create the children group.");
+    ///
+    ///     # let child_ref = &children_ref.elems()[0];
+    /// // Later, the message is "told" to the child...
+    /// child_ref.try_tell_anonymously(TELL_MSG).expect("Couldn't send the message.");
+    ///     #
+    ///     # Bastion::start();
+    ///     # Bastion::stop();
+    ///     # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn try_tell_anonymously<M: Message>(&self, msg: M) -> Result<(), SendError> {
+        debug!("ChildRef({}): Try Telling message: {:?}", self.id(), msg);
+        let msg = BastionMessage::tell(msg);
+        let env = Envelope::from_dead_letters(msg);
+        self.try_send(env).map_err(Into::into)
+    }
+
     /// Sends a message to the child this `ChildRef` is referencing,
     /// allowing it to answer.
     /// This message is intended to be used outside of Bastion context when
@@ -195,7 +301,18 @@ impl ChildRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     /// // The message that will be "asked"...
     /// const ASK_MSG: &'static str = "A message containing data (ask).";
@@ -254,11 +371,9 @@ impl ChildRef {
     ///     # Bastion::block_until_stopped();
     /// # }
     /// ```
-    ///
-    /// [`Answer`]: message/struct.Answer.html
     pub fn ask_anonymously<M: Message>(&self, msg: M) -> Result<Answer, M> {
         debug!("ChildRef({}): Asking message: {:?}", self.id(), msg);
-        let (msg, answer) = BastionMessage::ask(msg);
+        let (msg, answer) = BastionMessage::ask(msg, self.addr());
         let env = Envelope::from_dead_letters(msg);
         // FIXME: panics?
         self.send(env).map_err(|env| env.into_msg().unwrap())?;
@@ -266,6 +381,100 @@ impl ChildRef {
         Ok(answer)
     }
 
+    /// Try to send a message to the child this `ChildRef` is referencing,
+    /// allowing it to answer.
+    /// This message is intended to be used outside of Bastion context when
+    /// there is no way for receiver to identify message sender
+    ///
+    /// This method returns [`Answer`](../message/struct.Answer.html) if it succeeded, or a `SendError`(../child_ref/enum.SendError.html)
+    /// otherwise.
+    ///
+    /// # Argument
+    ///
+    /// * `msg` - The message to send.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    ///     # Bastion::init();
+    /// // The message that will be "asked"...
+    /// const ASK_MSG: &'static str = "A message containing data (ask).";
+    /// // The message the will be "answered"...
+    /// const ANSWER_MSG: &'static str = "A message containing data (answer).";
+    ///
+    ///     # let children_ref =
+    /// // Create a new child...
+    /// Bastion::children(|children| {
+    ///     children.with_exec(|ctx: BastionContext| {
+    ///         async move {
+    ///             // ...which will receive the message asked...
+    ///             msg! { ctx.recv().await?,
+    ///                 msg: &'static str =!> {
+    ///                     assert_eq!(msg, ASK_MSG);
+    ///                     // Handle the message...
+    ///
+    ///                     // ...and eventually answer to it...
+    ///                     answer!(ctx, ANSWER_MSG);
+    ///                 };
+    ///                 // This won't happen because this example
+    ///                 // only "asks" a `&'static str`...
+    ///                 _: _ => ();
+    ///             }
+    ///
+    ///             Ok(())
+    ///         }
+    ///     })
+    /// }).expect("Couldn't create the children group.");
+    ///
+    ///     # Bastion::children(|children| {
+    ///         # children.with_exec(move |ctx: BastionContext| {
+    ///             # let child_ref = children_ref.elems()[0].clone();
+    ///             # async move {
+    /// // Later, the message is "asked" to the child...
+    /// let answer: Answer = child_ref.try_ask_anonymously(ASK_MSG).expect("Couldn't send the message.");
+    ///
+    /// // ...and the child's answer is received...
+    /// msg! { answer.await.expect("Couldn't receive the answer."),
+    ///     msg: &'static str => {
+    ///         assert_eq!(msg, ANSWER_MSG);
+    ///         // Handle the answer...
+    ///     };
+    ///     // This won't happen because this example
+    ///     // only answers a `&'static str`...
+    ///     _: _ => ();
+    /// }
+    ///                 #
+    ///                 # Ok(())
+    ///             # }
+    ///         # })
+    ///     # }).unwrap();
+    ///     #
+    ///     # Bastion::start();
+    ///     # Bastion::stop();
+    ///     # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn try_ask_anonymously<M: Message>(&self, msg: M) -> Result<Answer, SendError> {
+        debug!("ChildRef({}): Try Asking message: {:?}", self.id(), msg);
+        let (msg, answer) = BastionMessage::ask(msg, self.addr());
+        let env = Envelope::from_dead_letters(msg);
+        self.try_send(env).map(|_| answer)
+    }
+
     /// Sends a message to the child this `ChildRef` is referencing
     /// to tell it to stop its execution.
     ///
@@ -277,6 +486,18 @@ impl ChildRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// # let children_ref =
     /// # Bastion::children(|children| {
@@ -304,6 +525,7 @@ impl ChildRef {
     ///     #
     ///     # Bastion::stop();
     ///     # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn stop(&self) -> Result<(), ()> {
         debug!("ChildRef({}): Stopping.", self.id);
@@ -323,6 +545,18 @@ impl ChildRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let children_ref = Bastion::children(|children| children).unwrap();
@@ -332,6 +566,7 @@ impl ChildRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn kill(&self) -> Result<(), ()> {
         debug!("ChildRef({}): Killing.", self.id());
@@ -352,6 +587,11 @@ impl ChildRef {
             .map_err(|err| err.into_inner())
     }
 
+    pub(crate) fn try_send(&self, env: Envelope) -> Result<(), SendError> {
+        trace!("ChildRef({}): Sending message: {:?}", self.id(), env);
+        self.sender.unbounded_send(env).map_err(Into::into)
+    }
+
     pub(crate) fn sender(&self) -> &Sender {
         &self.sender
     }
@@ -361,7 +601,7 @@ impl ChildRef {
         &self.path
     }
 
-    /// Return the [`name`] of the child
+    /// Return the `name` of the child
     pub fn name(&self) -> &str {
         &self.name
     }
diff --git a/src/bastion/src/children.rs b/src/bastion/src/children.rs
index 65d62372..84c8d412 100644
--- a/src/bastion/src/children.rs
+++ b/src/bastion/src/children.rs
@@ -1,6 +1,5 @@
 //!
 //! Children are a group of child supervised under a supervisor
-use crate::broadcast::{Broadcast, Parent, Sender};
 use crate::callbacks::{CallbackType, Callbacks};
 use crate::child::{Child, Init};
 use crate::child_ref::ChildRef;
@@ -8,13 +7,17 @@ use crate::children_ref::ChildrenRef;
 use crate::context::{BastionContext, BastionId, ContextState};
 use crate::dispatcher::Dispatcher;
 use crate::envelope::Envelope;
+use crate::global_system::SYSTEM;
 use crate::message::BastionMessage;
 use crate::path::BastionPathElement;
 #[cfg(feature = "scaling")]
 use crate::resizer::{ActorGroupStats, OptimalSizeExploringResizer, ScalingRule};
-use crate::system::SYSTEM;
+use crate::{
+    broadcast::{Broadcast, Parent, Sender},
+    distributor::Distributor,
+};
 use anyhow::Result as AnyResult;
-use async_mutex::Mutex;
+
 use bastion_executor::pool;
 use futures::pending;
 use futures::poll;
@@ -49,6 +52,18 @@ use tracing::{debug, trace, warn};
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 /// let children_ref: ChildrenRef = Bastion::children(|children| {
@@ -70,11 +85,12 @@ use tracing::{debug, trace, warn};
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 ///
-/// [`with_redundancy`]: #method.with_redundancy
-/// [`with_exec`]: #method.with_exec
-/// [`SupervisionStrategy`]: supervisor/enum.SupervisionStrategy.html
+/// [`with_redundancy`]: Self::with_redundancy
+/// [`with_exec`]: Self::with_exec
+/// [`SupervisionStrategy`]: crate::supervisor::SupervisionStrategy
 pub struct Children {
     bcast: Broadcast,
     // The currently launched elements of the group.
@@ -93,6 +109,7 @@ pub struct Children {
     started: bool,
     // List of dispatchers attached to each actor in the group.
     dispatchers: Vec<Arc<Box<Dispatcher>>>,
+    distributors: Vec<Distributor>,
     // The name of children
     name: Option<String>,
     #[cfg(feature = "scaling")]
@@ -118,6 +135,7 @@ impl Children {
         let pre_start_msgs = Vec::new();
         let started = false;
         let dispatchers = Vec::new();
+        let distributors = Vec::new();
         let name = None;
         #[cfg(feature = "scaling")]
         let resizer = Box::new(OptimalSizeExploringResizer::default());
@@ -133,6 +151,7 @@ impl Children {
             pre_start_msgs,
             started,
             dispatchers,
+            distributors,
             name,
             #[cfg(feature = "scaling")]
             resizer,
@@ -157,6 +176,18 @@ impl Children {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -168,6 +199,7 @@ impl Children {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn id(&self) -> &BastionId {
         self.bcast.id()
@@ -214,7 +246,9 @@ impl Children {
             .map(|dispatcher| dispatcher.dispatcher_type())
             .collect();
 
-        ChildrenRef::new(id, sender, path, children, dispatchers)
+        let distributors = self.distributors.clone();
+
+        ChildrenRef::new(id, sender, path, children, dispatchers, distributors)
     }
 
     /// Sets the name of this children group.
@@ -244,6 +278,18 @@ impl Children {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -263,6 +309,7 @@ impl Children {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn with_exec<I, F>(mut self, init: I) -> Self
     where
@@ -290,6 +337,18 @@ impl Children {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -300,9 +359,10 @@ impl Children {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`with_exec`]: #method.with_exec
+    /// [`with_exec`]: Self::with_exec
     pub fn with_redundancy(mut self, redundancy: usize) -> Self {
         trace!(
             "Children({}): Setting redundancy: {}",
@@ -314,6 +374,10 @@ impl Children {
         } else {
             self.redundancy = redundancy;
         }
+        #[cfg(feature = "scaling")]
+        {
+            self.resizer.set_lower_bound(self.redundancy as u64);
+        }
 
         self
     }
@@ -324,7 +388,7 @@ impl Children {
     ///
     /// # Arguments
     ///
-    /// * `redundancy` - An instance of struct that implements the
+    /// * `dispatcher` - An instance of struct that implements the
     /// [`DispatcherHandler`] trait.
     ///
     /// # Example
@@ -332,6 +396,18 @@ impl Children {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -344,13 +420,60 @@ impl Children {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    /// [`DispatcherHandler`]: ../dispatcher/trait.DispatcherHandler.html
+    /// [`DispatcherHandler`]: crate::dispatcher::DispatcherHandler
     pub fn with_dispatcher(mut self, dispatcher: Dispatcher) -> Self {
         self.dispatchers.push(Arc::new(Box::new(dispatcher)));
         self
     }
 
+    /// Appends a distributor to the children.
+    ///
+    /// By default supervised elements aren't added to any distributor.
+    ///
+    /// # Arguments
+    ///
+    /// * `distributor` - An instance of struct that implements the
+    /// [`RecipientHandler`] trait.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// #
+    /// Bastion::children(|children| {
+    ///     children
+    ///         .with_distributor(Distributor::named("my distributor"))
+    /// }).expect("Couldn't create the children group.");
+    /// #
+    /// # Bastion::start();
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    /// [`RecipientHandler`]: crate::dispatcher::RecipientHandler
+    pub fn with_distributor(mut self, distributor: Distributor) -> Self {
+        // Try to register the distributor as soon as we're aware of it
+        let _ = SYSTEM.dispatcher().register_distributor(&distributor);
+        self.distributors.push(distributor);
+        self
+    }
+
     #[cfg(feature = "scaling")]
     /// Sets a custom resizer for the Children.
     ///
@@ -365,11 +488,23 @@ impl Children {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     /// Bastion::children(|children| {
     ///     children
+    ///         .with_redundancy(1)
     ///         .with_resizer(
     ///             OptimalSizeExploringResizer::default()
     ///                 .with_lower_bound(10)
@@ -382,8 +517,8 @@ impl Children {
     ///     # Bastion::block_until_stopped();
     /// # }
     /// ```
-    /// [`Resizer`]: ../resizer/struct.Resizer.html
     pub fn with_resizer(mut self, resizer: OptimalSizeExploringResizer) -> Self {
+        self.redundancy = resizer.lower_bound() as usize;
         self.resizer = Box::new(resizer);
         self
     }
@@ -404,6 +539,18 @@ impl Children {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -426,9 +573,8 @@ impl Children {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Callbacks`]: struct.Callbacks.html
     pub fn with_callbacks(mut self, callbacks: Callbacks) -> Self {
         trace!(
             "Children({}): Setting callbacks: {:?}",
@@ -453,6 +599,18 @@ impl Children {
     /// # use bastion::prelude::*;
     /// # use std::time::Duration;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -471,8 +629,8 @@ impl Children {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    /// [`std::time::Duration`]: https://doc.rust-lang.org/nightly/core/time/struct.Duration.html
     pub fn with_heartbeat_tick(mut self, interval: Duration) -> Self {
         trace!(
             "Children({}): Set heartbeat tick to {:?}",
@@ -543,6 +701,9 @@ impl Children {
         if let Err(e) = self.remove_dispatchers() {
             warn!("couldn't remove all dispatchers from the registry: {}", e);
         };
+        if let Err(e) = self.remove_distributors() {
+            warn!("couldn't remove all distributors from the registry: {}", e);
+        };
         self.bcast.stopped();
     }
 
@@ -551,6 +712,9 @@ impl Children {
         if let Err(e) = self.remove_dispatchers() {
             warn!("couldn't remove all dispatchers from the registry: {}", e);
         };
+        if let Err(e) = self.remove_distributors() {
+            warn!("couldn't remove all distributors from the registry: {}", e);
+        };
         self.bcast.faulted();
     }
 
@@ -604,7 +768,7 @@ impl Children {
         }
     }
 
-    fn restart_child(&mut self, old_id: &BastionId, old_state: Arc<Mutex<Pin<Box<ContextState>>>>) {
+    fn restart_child(&mut self, old_id: &BastionId, old_state: Arc<Pin<Box<ContextState>>>) {
         let parent = Parent::children(self.as_ref());
         let bcast = Broadcast::new(parent, BastionPathElement::Child(old_id.clone()));
 
@@ -616,14 +780,12 @@ impl Children {
         let children = self.as_ref();
         let supervisor = self.bcast.parent().clone().into_supervisor();
 
-        let state = Arc::new(Mutex::new(Box::pin(ContextState::new())));
-
         let ctx = BastionContext::new(
             id.clone(),
             child_ref.clone(),
             children,
             supervisor,
-            state.clone(),
+            old_state.clone(),
         );
         let exec = (self.init.0)(ctx);
 
@@ -643,6 +805,7 @@ impl Children {
 
         debug!("Children({}): Restarting Child({}).", self.id(), bcast.id());
         let callbacks = self.callbacks.clone();
+        let state = Arc::new(Box::pin(ContextState::new()));
         let child = Child::new(exec, callbacks, bcast, state, child_ref);
         debug!(
             "Children({}): Launching faulted Child({}).",
@@ -890,7 +1053,7 @@ impl Children {
         #[cfg(feature = "scaling")]
         self.init_data_for_scaling(&mut state);
 
-        let state = Arc::new(Mutex::new(Box::pin(state)));
+        let state = Arc::new(Box::pin(state));
 
         let ctx = BastionContext::new(
             id.clone(),
@@ -939,7 +1102,7 @@ impl Children {
         let children = self.as_ref();
         let supervisor = self.bcast.parent().clone().into_supervisor();
 
-        let state = Arc::new(Mutex::new(Box::pin(ContextState::new())));
+        let state = Arc::new(Box::pin(ContextState::new()));
 
         let ctx = BastionContext::new(id, child_ref.clone(), children, supervisor, state.clone());
         let init = self.get_heartbeat_fut();
@@ -997,4 +1160,24 @@ impl Children {
         }
         Ok(())
     }
+
+    /// Registers all declared local distributors in the global dispatcher.
+    pub(crate) fn register_distributors(&self) -> AnyResult<()> {
+        let global_dispatcher = SYSTEM.dispatcher();
+
+        for distributor in self.distributors.iter() {
+            global_dispatcher.register_distributor(distributor)?;
+        }
+        Ok(())
+    }
+
+    /// Removes all declared local distributors from the global dispatcher.
+    pub(crate) fn remove_distributors(&self) -> AnyResult<()> {
+        let global_dispatcher = SYSTEM.dispatcher();
+
+        for distributor in self.distributors.iter() {
+            global_dispatcher.remove_distributor(distributor)?;
+        }
+        Ok(())
+    }
 }
diff --git a/src/bastion/src/children_ref.rs b/src/bastion/src/children_ref.rs
index 44313d61..2cd2063b 100644
--- a/src/bastion/src/children_ref.rs
+++ b/src/bastion/src/children_ref.rs
@@ -1,13 +1,13 @@
 //!
 //! Allows users to communicate with children through the mailboxes.
 use crate::broadcast::Sender;
-use crate::child_ref::ChildRef;
 use crate::context::BastionId;
 use crate::dispatcher::DispatcherType;
 use crate::envelope::Envelope;
+use crate::global_system::SYSTEM;
 use crate::message::{BastionMessage, Message};
 use crate::path::BastionPath;
-use crate::system::SYSTEM;
+use crate::{child_ref::ChildRef, distributor::Distributor};
 use std::cmp::{Eq, PartialEq};
 use std::fmt::Debug;
 use std::sync::Arc;
@@ -22,6 +22,7 @@ pub struct ChildrenRef {
     path: Arc<BastionPath>,
     children: Vec<ChildRef>,
     dispatchers: Vec<DispatcherType>,
+    distributors: Vec<Distributor>,
 }
 
 impl ChildrenRef {
@@ -31,6 +32,7 @@ impl ChildrenRef {
         path: Arc<BastionPath>,
         children: Vec<ChildRef>,
         dispatchers: Vec<DispatcherType>,
+        distributors: Vec<Distributor>,
     ) -> Self {
         ChildrenRef {
             id,
@@ -38,6 +40,7 @@ impl ChildrenRef {
             path,
             children,
             dispatchers,
+            distributors,
         }
     }
 
@@ -52,6 +55,18 @@ impl ChildrenRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// let children_ref = Bastion::children(|children| {
@@ -64,6 +79,7 @@ impl ChildrenRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn id(&self) -> &BastionId {
         &self.id
@@ -77,6 +93,18 @@ impl ChildrenRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let children_ref = Bastion::children(|children| children).unwrap();
@@ -85,13 +113,46 @@ impl ChildrenRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`ChildRef`]: children/struct.ChildRef.html
     pub fn dispatchers(&self) -> &Vec<DispatcherType> {
         &self.dispatchers
     }
 
+    /// Returns a list of distributors that can be used for
+    /// communication with other actors in the same group(s).
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// #
+    /// # let children_ref = Bastion::children(|children| children).unwrap();
+    /// let distributors = children_ref.distributors();
+    /// #
+    /// # Bastion::start();
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn distributors(&self) -> &Vec<Distributor> {
+        &self.distributors
+    }
+
     /// Returns a list of [`ChildRef`] referencing the elements
     /// of the children group this `ChildrenRef` is referencing.
     ///
@@ -100,6 +161,18 @@ impl ChildrenRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let children_ref = Bastion::children(|children| children).unwrap();
@@ -108,9 +181,8 @@ impl ChildrenRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`ChildRef`]: children/struct.ChildRef.html
     pub fn elems(&self) -> &[ChildRef] {
         &self.children
     }
@@ -135,7 +207,18 @@ impl ChildrenRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     ///     # let children_ref = Bastion::children(|children| children).unwrap();
@@ -166,7 +249,7 @@ impl ChildrenRef {
     /// # }
     /// ```
     ///
-    /// [`elems`]: #method.elems
+    /// [`elems`]: Self::elems
     pub fn broadcast<M: Message>(&self, msg: M) -> Result<(), M> {
         debug!(
             "ChildrenRef({}): Broadcasting message: {:?}",
@@ -191,6 +274,18 @@ impl ChildrenRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let children_ref = Bastion::children(|children| children).unwrap();
@@ -199,6 +294,7 @@ impl ChildrenRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn stop(&self) -> Result<(), ()> {
         debug!("ChildrenRef({}): Stopping.", self.id());
@@ -219,6 +315,18 @@ impl ChildrenRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let children_ref = Bastion::children(|children| children).unwrap();
@@ -227,6 +335,7 @@ impl ChildrenRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn kill(&self) -> Result<(), ()> {
         debug!("ChildrenRef({}): Killing.", self.id());
diff --git a/src/bastion/src/config.rs b/src/bastion/src/config.rs
index ceecf258..118e121e 100644
--- a/src/bastion/src/config.rs
+++ b/src/bastion/src/config.rs
@@ -10,6 +10,18 @@
 /// ```rust
 /// use bastion::prelude::*;
 ///
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// let config = Config::new().show_backtraces();
 ///
 /// Bastion::init_with(config);
@@ -19,9 +31,10 @@
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 ///
-/// [`Bastion::init_with`]: struct.Bastion.html#method.init_with
+/// [`Bastion::init_with`]: crate::Bastion::init_with
 pub struct Config {
     backtraces: Backtraces,
 }
@@ -40,8 +53,6 @@ impl Config {
     /// Creates a new configuration with the following default
     /// behaviors:
     /// - All backtraces are shown (see [`Config::show_backtraces`]).
-    ///
-    /// [`Config::show_backtraces`]: #method.show_backtraces
     pub fn new() -> Self {
         Config::default()
     }
@@ -57,6 +68,18 @@ impl Config {
     /// ```rust
     /// use bastion::prelude::*;
     ///
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// let config = Config::new().show_backtraces();
     ///
     /// Bastion::init_with(config);
@@ -67,6 +90,7 @@ impl Config {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn show_backtraces(mut self) -> Self {
         self.backtraces = Backtraces::show();
@@ -83,6 +107,18 @@ impl Config {
     /// ```rust
     /// use bastion::prelude::*;
     ///
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// let config = Config::new().hide_backtraces();
     ///
     /// Bastion::init_with(config);
@@ -93,9 +129,8 @@ impl Config {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Config::show_backtraces`]: #method.show_backtraces
     pub fn hide_backtraces(mut self) -> Self {
         self.backtraces = Backtraces::hide();
         self
diff --git a/src/bastion/src/context.rs b/src/bastion/src/context.rs
index de805830..93967da4 100644
--- a/src/bastion/src/context.rs
+++ b/src/bastion/src/context.rs
@@ -8,14 +8,14 @@ use crate::dispatcher::{BroadcastTarget, DispatcherType, NotificationType};
 use crate::envelope::{Envelope, RefAddr, SignedMessage};
 use crate::message::{Answer, BastionMessage, Message, Msg};
 use crate::supervisor::SupervisorRef;
-use crate::{prelude::ReceiveError, system::SYSTEM};
-use async_mutex::Mutex;
+use crate::{global_system::SYSTEM, prelude::ReceiveError};
+
+use crossbeam_queue::SegQueue;
 use futures::pending;
 use futures::FutureExt;
 use futures_timer::Delay;
 #[cfg(feature = "scaling")]
 use lever::table::lotable::LOTable;
-use std::collections::VecDeque;
 use std::fmt::{self, Display, Formatter};
 use std::pin::Pin;
 #[cfg(feature = "scaling")]
@@ -42,6 +42,18 @@ pub const NIL_ID: BastionId = BastionId(Uuid::nil());
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 /// Bastion::children(|children| {
@@ -57,11 +69,12 @@ pub const NIL_ID: BastionId = BastionId(Uuid::nil());
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 pub struct BastionId(pub(crate) Uuid);
 
 #[derive(Debug)]
-/// A child's execution context, allowing its [`exec`] future
+/// A child's execution context, allowing its [`with_exec`] future
 /// to receive messages and access a [`ChildRef`] referencing
 /// it, a [`ChildrenRef`] referencing its children group and
 /// a [`SupervisorRef`] referencing its supervisor.
@@ -71,6 +84,18 @@ pub struct BastionId(pub(crate) Uuid);
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 /// Bastion::children(|children| {
@@ -103,18 +128,21 @@ pub struct BastionId(pub(crate) Uuid);
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
+///
+/// [`with_exec`]: crate::children::Children::with_exec
 pub struct BastionContext {
     id: BastionId,
     child: ChildRef,
     children: ChildrenRef,
     supervisor: Option<SupervisorRef>,
-    state: Arc<Mutex<Pin<Box<ContextState>>>>,
+    state: Arc<Pin<Box<ContextState>>>,
 }
 
 #[derive(Debug)]
 pub(crate) struct ContextState {
-    messages: VecDeque<SignedMessage>,
+    messages: SegQueue<SignedMessage>,
     #[cfg(feature = "scaling")]
     stats: Arc<AtomicU64>,
     #[cfg(feature = "scaling")]
@@ -135,7 +163,7 @@ impl BastionContext {
         child: ChildRef,
         children: ChildrenRef,
         supervisor: Option<SupervisorRef>,
-        state: Arc<Mutex<Pin<Box<ContextState>>>>,
+        state: Arc<Pin<Box<ContextState>>>,
     ) -> Self {
         debug!("BastionContext({}): Creating.", id);
         BastionContext {
@@ -155,6 +183,18 @@ impl BastionContext {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -172,9 +212,8 @@ impl BastionContext {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`ChildRef`]: children/struct.ChildRef.html
     pub fn current(&self) -> &ChildRef {
         &self.child
     }
@@ -187,6 +226,18 @@ impl BastionContext {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -204,9 +255,8 @@ impl BastionContext {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`ChildrenRef`]: children/struct.ChildrenRef.html
     pub fn parent(&self) -> &ChildrenRef {
         &self.children
     }
@@ -222,6 +272,18 @@ impl BastionContext {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// // When calling the method from a children group supervised
@@ -258,9 +320,9 @@ impl BastionContext {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`SupervisorRef`]: supervisor/struct.SupervisorRef.html
     /// [`Bastion::children`]: struct.Bastion.html#method.children
     pub fn supervisor(&self) -> Option<&SupervisorRef> {
         self.supervisor.as_ref()
@@ -283,6 +345,18 @@ impl BastionContext {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -300,23 +374,25 @@ impl BastionContext {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`recv`]: #method.recv
-    /// [`try_recv_timeout`]: #method.try_recv_timeout
-    /// [`SignedMessage`]: ../prelude/struct.SignedMessage.html
+    /// [`recv`]: Self::method.recv
+    /// [`try_recv_timeout`]: Self::method.try_recv_timeout
     pub async fn try_recv(&self) -> Option<SignedMessage> {
-        self.try_recv_timeout(std::time::Duration::from_nanos(0))
-            .await
-            .map(|msg| {
-                trace!("BastionContext({}): Received message: {:?}", self.id, msg);
-                msg
-            })
-            .map_err(|e| {
-                trace!("BastionContext({}): Received no message.", self.id);
-                e
-            })
-            .ok()
+        // We want to let a tick pass
+        // otherwise guard will never contain anything.
+        Delay::new(Duration::from_millis(0)).await;
+
+        trace!("BastionContext({}): Trying to receive message.", self.id);
+
+        if let Some(msg) = self.state.pop_message() {
+            trace!("BastionContext({}): Received message: {:?}", self.id, msg);
+            Some(msg)
+        } else {
+            trace!("BastionContext({}): Received no message.", self.id);
+            None
+        }
     }
 
     /// Retrieves asynchronously a message received by the element
@@ -337,6 +413,18 @@ impl BastionContext {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -353,23 +441,18 @@ impl BastionContext {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`try_recv`]: #method.try_recv
-    /// [`try_recv_timeout`]: #method.try_recv_timeout
-    /// [`SignedMessage`]: ../prelude/struct.SignedMessage.html
+    /// [`try_recv`]: Self::try_recv
+    /// [`try_recv_timeout`]: Self::try_recv_timeout
     pub async fn recv(&self) -> Result<SignedMessage, ()> {
         debug!("BastionContext({}): Waiting to receive message.", self.id);
         loop {
-            let state = self.state.clone();
-            let mut guard = state.lock().await;
-
-            if let Some(msg) = guard.pop_message() {
+            if let Some(msg) = self.state.pop_message() {
                 trace!("BastionContext({}): Received message: {:?}", self.id, msg);
                 return Ok(msg);
             }
-
-            drop(guard);
             pending!();
         }
     }
@@ -393,6 +476,18 @@ impl BastionContext {
     /// # use bastion::prelude::*;
     /// # use std::time::Duration;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -414,26 +509,23 @@ impl BastionContext {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`recv`]: #method.recv
-    /// [`try_recv`]: #method.try_recv
-    /// [`SignedMessage`]: ../prelude/struct.SignedMessage.html
+    /// [`recv`]: Self::recv
+    /// [`try_recv`]: Self::try_recv
+    /// [`SignedMessage`]: .crate::enveloppe::SignedMessage
     pub async fn try_recv_timeout(&self, timeout: Duration) -> Result<SignedMessage, ReceiveError> {
-        if timeout == std::time::Duration::from_nanos(0) {
-            debug!("BastionContext({}): Trying to receive message.", self.id);
-        } else {
-            debug!(
-                "BastionContext({}): Waiting to receive message within {} milliseconds.",
-                self.id,
-                timeout.as_millis()
-            );
-        }
+        debug!(
+            "BastionContext({}): Waiting to receive message within {} milliseconds.",
+            self.id,
+            timeout.as_millis()
+        );
         futures::select! {
             message = self.recv().fuse() => {
                 message.map_err(|_| ReceiveError::Other)
             },
-            duration = Delay::new(timeout).fuse() => {
+            _duration = Delay::new(timeout).fuse() => {
                 Err(ReceiveError::Timeout(timeout))
             }
         }
@@ -446,6 +538,18 @@ impl BastionContext {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     ///
@@ -462,9 +566,11 @@ impl BastionContext {
     /// #
     /// # Bastion::start();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`RefAddr`]: /prelude/struct.Answer.html
+    // TODO(scrabsha): should we link to Answer or to RefAddr?
+    // [`RefAddr`]: /prelude/struct.Answer.html
     pub fn signature(&self) -> RefAddr {
         RefAddr::new(
             self.current().path().clone(),
@@ -484,6 +590,18 @@ impl BastionContext {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -503,9 +621,8 @@ impl BastionContext {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`RefAddr`]: ../prelude/struct.RefAddr.html
     pub fn tell<M: Message>(&self, to: &RefAddr, msg: M) -> Result<(), M> {
         debug!(
             "{:?}: Telling message: {:?} to: {:?}",
@@ -536,7 +653,18 @@ impl BastionContext {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     /// // The message that will be "asked"...
     /// const ASK_MSG: &'static str = "A message containing data (ask).";
@@ -595,8 +723,6 @@ impl BastionContext {
     ///     # Bastion::block_until_stopped();
     /// # }
     /// ```
-    ///
-    /// [`Answer`]: /message/struct.Answer.html
     pub fn ask<M: Message>(&self, to: &RefAddr, msg: M) -> Result<Answer, M> {
         debug!(
             "{:?}: Asking message: {:?} to: {:?}",
@@ -604,7 +730,7 @@ impl BastionContext {
             msg,
             to
         );
-        let (msg, answer) = BastionMessage::ask(msg);
+        let (msg, answer) = BastionMessage::ask(msg, self.signature());
         let env = Envelope::new_with_sign(msg, self.signature());
         // FIXME: panics?
         to.sender()
@@ -636,7 +762,6 @@ impl BastionContext {
     /// the [`BroadcastTarget`] value.
     /// * `message` - The broadcasted message.
     ///
-    /// [`BroadcastTarget`]: ../dispatcher/enum.DispatcherType.html
     pub fn broadcast_message<M: Message>(&self, target: BroadcastTarget, message: M) {
         let msg = Arc::new(SignedMessage {
             msg: Msg::broadcast(message),
@@ -651,7 +776,7 @@ impl BastionContext {
 impl ContextState {
     pub(crate) fn new() -> Self {
         ContextState {
-            messages: VecDeque::new(),
+            messages: SegQueue::new(),
             #[cfg(feature = "scaling")]
             stats: Arc::new(AtomicU64::new(0)),
             #[cfg(feature = "scaling")]
@@ -679,12 +804,12 @@ impl ContextState {
         self.actor_stats.clone()
     }
 
-    pub(crate) fn push_message(&mut self, msg: Msg, sign: RefAddr) {
-        self.messages.push_back(SignedMessage::new(msg, sign))
+    pub(crate) fn push_message(&self, msg: Msg, sign: RefAddr) {
+        self.messages.push(SignedMessage::new(msg, sign))
     }
 
-    pub(crate) fn pop_message(&mut self) -> Option<SignedMessage> {
-        self.messages.pop_front()
+    pub(crate) fn pop_message(&self) -> Option<SignedMessage> {
+        self.messages.pop()
     }
 
     #[cfg(feature = "scaling")]
@@ -706,19 +831,31 @@ mod context_tests {
     use crate::Bastion;
     use std::panic;
 
-    #[test]
+    #[cfg(feature = "tokio-runtime")]
+    mod tokio_tests {
+        #[tokio::test]
+        async fn test_context() {
+            super::test_context()
+        }
+    }
+
+    #[cfg(not(feature = "tokio-runtime"))]
+    mod no_tokio_tests {
+        #[test]
+        fn test_context() {
+            super::test_context()
+        }
+    }
+
     fn test_context() {
         Bastion::init();
         Bastion::start();
 
-        run_test(test_recv);
-        run_test(test_try_recv);
-        run_test(test_try_recv_fail);
-        run_test(test_try_recv_timeout);
-        run_test(test_try_recv_timeout_fail);
-
-        Bastion::stop();
-        Bastion::block_until_stopped();
+        test_recv();
+        test_try_recv();
+        test_try_recv_fail();
+        test_try_recv_timeout();
+        test_try_recv_timeout_fail();
     }
 
     fn test_recv() {
@@ -762,7 +899,7 @@ mod context_tests {
     }
 
     fn test_try_recv_fail() {
-        let children = Bastion::children(|children| {
+        Bastion::children(|children| {
             children.with_exec(|ctx: BastionContext| async move {
                 assert!(ctx.try_recv().await.is_none());
                 Ok(())
@@ -777,7 +914,7 @@ mod context_tests {
         let children =
         Bastion::children(|children| {
             children.with_exec(|ctx: BastionContext| async move {
-                msg! { ctx.try_recv_timeout(std::time::Duration::from_millis(1)).await.expect("recv_timeout failed"),
+                msg! { ctx.try_recv_timeout(std::time::Duration::from_millis(5)).await.expect("recv_timeout failed"),
                     ref msg: &'static str => {
                         assert_eq!(msg, &"test recv timeout");
                     };
@@ -809,15 +946,6 @@ mod context_tests {
         run!(async { Delay::new(std::time::Duration::from_millis(2)).await });
 
         // The child panicked, but we should still be able to send things to it
-        assert!(children.broadcast("test recv timeout").is_ok());
-    }
-
-    fn run_test<T>(test: T) -> ()
-    where
-        T: FnOnce() -> () + panic::UnwindSafe,
-    {
-        let result = panic::catch_unwind(|| test());
-
-        assert!(result.is_ok())
+        children.broadcast("test recv timeout").unwrap();
     }
 }
diff --git a/src/bastion/src/dispatcher.rs b/src/bastion/src/dispatcher.rs
index 7306e9d8..4596659c 100644
--- a/src/bastion/src/dispatcher.rs
+++ b/src/bastion/src/dispatcher.rs
@@ -2,22 +2,34 @@
 //! Special module that allows users to interact and communicate with a
 //! group of actors through the dispatchers that holds information about
 //! actors grouped together.
-use crate::child_ref::ChildRef;
-use crate::envelope::SignedMessage;
+use crate::{
+    child_ref::ChildRef,
+    message::{Answer, Message},
+    prelude::SendError,
+};
+use crate::{distributor::Distributor, envelope::SignedMessage};
 use anyhow::Result as AnyResult;
 use lever::prelude::*;
-use std::fmt::{self, Debug};
 use std::hash::{Hash, Hasher};
+use std::sync::RwLock;
 use std::sync::{
     atomic::{AtomicUsize, Ordering},
     Arc,
 };
-use tracing::{debug, trace, warn};
+use std::{
+    collections::HashMap,
+    fmt::{self, Debug},
+};
+use tracing::{debug, trace};
 
 /// Type alias for the concurrency hashmap. Each key-value pair stores
 /// the Bastion identifier as the key and the module name as the value.
 pub type DispatcherMap = LOTable<ChildRef, String>;
 
+/// Type alias for the recipients hashset.
+/// Each key-value pair stores the Bastion identifier as the key.
+pub type RecipientMap = LOTable<ChildRef, ()>;
+
 #[derive(Debug, Clone)]
 /// Defines types of the notifications handled by the dispatcher
 /// when the group of actors is changing.
@@ -43,6 +55,27 @@ pub enum BroadcastTarget {
     Group(String),
 }
 
+/// A `Recipient` is responsible for maintaining it's list
+/// of recipients, and deciding which child gets to receive which message.
+pub trait Recipient {
+    /// Provide this function to declare which recipient will receive the next message
+    fn next(&self) -> Option<ChildRef>;
+    /// Return all recipients that will receive a broadcast message
+    fn all(&self) -> Vec<ChildRef>;
+    /// Add this actor to your list of recipients
+    fn register(&self, actor: ChildRef);
+    /// Remove this actor from your list of recipients
+    fn remove(&self, actor: &ChildRef);
+}
+
+/// A `RecipientHandler` is a `Recipient` implementor, that can be stored in the dispatcher
+pub trait RecipientHandler: Recipient + Send + Sync + Debug {}
+
+impl RecipientHandler for RoundRobinHandler {}
+
+/// The default handler, which does round-robin.
+pub type DefaultRecipientHandler = RoundRobinHandler;
+
 #[derive(Debug, Clone, Eq, PartialEq)]
 /// Defines the type of the dispatcher.
 ///
@@ -67,6 +100,48 @@ pub type DefaultDispatcherHandler = RoundRobinHandler;
 #[derive(Default, Debug)]
 pub struct RoundRobinHandler {
     index: AtomicUsize,
+    recipients: RecipientMap,
+}
+
+impl RoundRobinHandler {
+    fn public_recipients(&self) -> Vec<ChildRef> {
+        self.recipients
+            .iter()
+            .filter_map(|entry| {
+                if entry.0.is_public() {
+                    Some(entry.0)
+                } else {
+                    None
+                }
+            })
+            .collect()
+    }
+}
+
+impl Recipient for RoundRobinHandler {
+    fn next(&self) -> Option<ChildRef> {
+        let entries = self.public_recipients();
+
+        if entries.is_empty() {
+            return None;
+        }
+
+        let current_index = self.index.load(Ordering::SeqCst) % entries.len();
+        self.index.store(current_index + 1, Ordering::SeqCst);
+        entries.get(current_index).map(std::clone::Clone::clone)
+    }
+
+    fn all(&self) -> Vec<ChildRef> {
+        self.public_recipients()
+    }
+
+    fn register(&self, actor: ChildRef) {
+        let _ = self.recipients.insert(actor, ());
+    }
+
+    fn remove(&self, actor: &ChildRef) {
+        let _ = self.recipients.remove(&actor);
+    }
 }
 
 impl DispatcherHandler for RoundRobinHandler {
@@ -80,25 +155,31 @@ impl DispatcherHandler for RoundRobinHandler {
     }
     // Each child in turn will receive a message.
     fn broadcast_message(&self, entries: &DispatcherMap, message: &Arc<SignedMessage>) {
-        let entries = entries
+        let public_childrefs = entries
             .iter()
-            .filter(|entry| entry.0.is_public())
+            .filter_map(|entry| {
+                if entry.0.is_public() {
+                    Some(entry.0)
+                } else {
+                    None
+                }
+            })
             .collect::<Vec<_>>();
 
-        if entries.is_empty() {
+        if public_childrefs.is_empty() {
             debug!("no public children to broadcast message to");
             return;
         }
-        let current_index = self.index.load(Ordering::SeqCst) % entries.len();
+        let current_index = self.index.load(Ordering::SeqCst) % public_childrefs.len();
 
-        if let Some(entry) = entries.get(current_index) {
-            warn!(
+        if let Some(entry) = public_childrefs.get(current_index) {
+            debug!(
                 "sending message to child {}/{} - {}",
                 current_index + 1,
                 entries.len(),
-                entry.0.path()
+                entry.path()
             );
-            entry.0.tell_anonymously(message.clone()).unwrap();
+            entry.tell_anonymously(message.clone()).unwrap();
             self.index.store(current_index + 1, Ordering::SeqCst);
         };
     }
@@ -269,6 +350,8 @@ impl Into<DispatcherType> for String {
 pub(crate) struct GlobalDispatcher {
     /// Storage for all registered group of actors.
     pub dispatchers: LOTable<DispatcherType, Arc<Box<Dispatcher>>>,
+    // TODO: switch to LOTable once lever implements write optimized granularity
+    pub distributors: Arc<RwLock<HashMap<Distributor, Box<(dyn RecipientHandler)>>>>,
 }
 
 impl GlobalDispatcher {
@@ -276,6 +359,12 @@ impl GlobalDispatcher {
     pub(crate) fn new() -> Self {
         GlobalDispatcher {
             dispatchers: LOTable::new(),
+            distributors: Arc::new(RwLock::new(HashMap::new()))
+            // TODO: switch to LOTable once lever implements write optimized granularity
+            // distributors: LOTableBuilder::new()
+                //.with_concurrency(TransactionConcurrency::Optimistic)
+                //.with_isolation(TransactionIsolation::Serializable)
+                //.build(),
         }
     }
 
@@ -332,19 +421,17 @@ impl GlobalDispatcher {
 
     /// Broadcasts the given message in according with the specified target.
     pub(crate) fn broadcast_message(&self, target: BroadcastTarget, message: &Arc<SignedMessage>) {
-        let mut acked_dispatchers: Vec<DispatcherType> = Vec::new();
-
-        match target {
+        let acked_dispatchers = match target {
             BroadcastTarget::All => self
                 .dispatchers
                 .iter()
                 .map(|pair| pair.0.name().into())
-                .for_each(|group_name| acked_dispatchers.push(group_name)),
+                .collect(),
             BroadcastTarget::Group(name) => {
                 let target_dispatcher = name.into();
-                acked_dispatchers.push(target_dispatcher);
+                vec![target_dispatcher]
             }
-        }
+        };
 
         for dispatcher_type in acked_dispatchers {
             match self.dispatchers.get(&dispatcher_type) {
@@ -354,7 +441,7 @@ impl GlobalDispatcher {
                 // TODO: Put the message into the dead queue
                 None => {
                     let name = dispatcher_type.name();
-                    warn!(
+                    debug!(
                         "The message can't be delivered to the group with the '{}' name.",
                         name
                     );
@@ -363,13 +450,95 @@ impl GlobalDispatcher {
         }
     }
 
+    pub(crate) fn tell<M>(&self, distributor: Distributor, message: M) -> Result<(), SendError>
+    where
+        M: Message,
+    {
+        let child = self.next(distributor)?.ok_or(SendError::EmptyRecipient)?;
+        child.try_tell_anonymously(message).map(Into::into)
+    }
+
+    pub(crate) fn ask<M>(&self, distributor: Distributor, message: M) -> Result<Answer, SendError>
+    where
+        M: Message,
+    {
+        let child = self.next(distributor)?.ok_or(SendError::EmptyRecipient)?;
+        child.try_ask_anonymously(message).map(Into::into)
+    }
+
+    pub(crate) fn ask_everyone<M>(
+        &self,
+        distributor: Distributor,
+        message: M,
+    ) -> Result<Vec<Answer>, SendError>
+    where
+        M: Message + Clone,
+    {
+        let all_children = self.all(distributor)?;
+        if all_children.is_empty() {
+            Err(SendError::EmptyRecipient)
+        } else {
+            all_children
+                .iter()
+                .map(|child| child.try_ask_anonymously(message.clone()))
+                .collect::<Result<Vec<_>, _>>()
+        }
+    }
+
+    pub(crate) fn tell_everyone<M>(
+        &self,
+        distributor: Distributor,
+        message: M,
+    ) -> Result<Vec<()>, SendError>
+    where
+        M: Message + Clone,
+    {
+        let all_children = self.all(distributor)?;
+        if all_children.is_empty() {
+            Err(SendError::EmptyRecipient)
+        } else {
+            all_children
+                .iter()
+                .map(|child| child.try_tell_anonymously(message.clone()))
+                .collect()
+        }
+    }
+
+    fn next(&self, distributor: Distributor) -> Result<Option<ChildRef>, SendError> {
+        self.distributors
+            .read()
+            .map_err(|error| {
+                SendError::Other(anyhow::anyhow!(
+                    "couldn't get read lock on distributors {:?}",
+                    error
+                ))
+            })?
+            .get(&distributor)
+            .map(|recipient| recipient.next())
+            .ok_or_else(|| SendError::from(distributor))
+    }
+
+    fn all(&self, distributor: Distributor) -> Result<Vec<ChildRef>, SendError> {
+        self.distributors
+            .read()
+            .map_err(|error| {
+                SendError::Other(anyhow::anyhow!(
+                    "couldn't get read lock on distributors {:?}",
+                    error
+                ))
+            })?
+            .get(&distributor)
+            .map(|recipient| recipient.all())
+            .ok_or_else(|| SendError::from(distributor))
+    }
+
     /// Adds dispatcher to the global registry.
     pub(crate) fn register_dispatcher(&self, dispatcher: &Arc<Box<Dispatcher>>) -> AnyResult<()> {
         let dispatcher_type = dispatcher.dispatcher_type();
         let is_registered = self.dispatchers.contains_key(&dispatcher_type);
 
         if is_registered && dispatcher_type != DispatcherType::Anonymous {
-            warn!(
+            debug!(
                 "The dispatcher with the '{:?}' name already registered in the cluster.",
                 dispatcher_type
             );
@@ -386,6 +555,72 @@ impl GlobalDispatcher {
         self.dispatchers.remove(&dispatcher.dispatcher_type())?;
         Ok(())
     }
+
+    /// Appends the information about actor to the recipients.
+    pub(crate) fn register_recipient(
+        &self,
+        distributor: &Distributor,
+        child_ref: ChildRef,
+    ) -> AnyResult<()> {
+        let mut distributors = self.distributors.write().map_err(|error| {
+            anyhow::anyhow!("couldn't get read lock on distributors {:?}", error)
+        })?;
+        if let Some(recipients) = distributors.get(&distributor) {
+            recipients.register(child_ref);
+        } else {
+            let recipients = DefaultRecipientHandler::default();
+            recipients.register(child_ref);
+            distributors.insert(
+                distributor.clone(),
+                Box::new(recipients) as Box<(dyn RecipientHandler)>,
+            );
+        };
+        Ok(())
+    }
+
+    pub(crate) fn remove_recipient(
+        &self,
+        distributor_list: &[Distributor],
+        child_ref: ChildRef,
+    ) -> AnyResult<()> {
+        let distributors = self.distributors.write().map_err(|error| {
+            anyhow::anyhow!("couldn't get read lock on distributors {:?}", error)
+        })?;
+        distributor_list.iter().for_each(|distributor| {
+            distributors
+                .get(&distributor)
+                .map(|recipients| recipients.remove(&child_ref));
+        });
+        Ok(())
+    }
+
+    /// Adds distributor to the global registry.
+    pub(crate) fn register_distributor(&self, distributor: &Distributor) -> AnyResult<()> {
+        let mut distributors = self.distributors.write().map_err(|error| {
+            anyhow::anyhow!("couldn't get read lock on distributors {:?}", error)
+        })?;
+        if distributors.contains_key(&distributor) {
+            debug!(
+                "The distributor with the '{:?}' name already registered in the cluster.",
+                distributor
+            );
+        } else {
+            distributors.insert(
+                distributor.clone(),
+                Box::new(DefaultRecipientHandler::default()),
+            );
+        }
+        Ok(())
+    }
+
+    /// Removes distributor from the global registry.
+    pub(crate) fn remove_distributor(&self, distributor: &Distributor) -> AnyResult<()> {
+        let mut distributors = self.distributors.write().map_err(|error| {
+            anyhow::anyhow!("couldn't get read lock on distributors {:?}", error)
+        })?;
+        distributors.remove(distributor);
+        Ok(())
+    }
 }
 
 #[cfg(test)]
diff --git a/src/bastion/src/distributor.rs b/src/bastion/src/distributor.rs
new file mode 100644
index 00000000..646b42aa
--- /dev/null
+++ b/src/bastion/src/distributor.rs
@@ -0,0 +1,750 @@
+//! `Distributor` is a mechanism that allows you to send messages to children.
+
+use crate::{
+    global_system::{STRING_INTERNER, SYSTEM},
+    message::{Answer, Message, MessageHandler},
+    prelude::{ChildRef, SendError},
+};
+use anyhow::Result as AnyResult;
+use futures::channel::oneshot;
+use lasso::Spur;
+use std::{
+    fmt::Debug,
+    sync::mpsc::{channel, Receiver},
+};
+
+// Copy is fine here because we're working
+// with interned strings here
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+/// The `Distributor` is the main message passing mechanism we will use.
+/// it provides methods that will allow us to send messages
+/// and add/remove actors to the Distribution list
+pub struct Distributor(Spur);
+
+impl Distributor {
+    /// Create a new distributor to send messages to
+    /// # Example
+    ///
+    /// ```rust
+    /// # use bastion::prelude::*;
+    /// #
+    /// #
+    /// # fn run() {
+    /// #
+    /// let distributor = Distributor::named("my target group");
+    /// // distributor is now ready to use
+    /// # }
+    /// ```
+    pub fn named(name: impl AsRef<str>) -> Self {
+        Self(STRING_INTERNER.get_or_intern(name.as_ref()))
+    }
+
+    /// Ask a question to a recipient attached to the `Distributor`
+    /// and wait for a reply.
+    ///
+    /// This can be achieved manually using a `MessageHandler` and `ask_one`.
+    /// Ask a question to a recipient attached to the `Distributor`
+    ///
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # async fn run() {
+    /// # Bastion::init();
+    /// # Bastion::start();
+    ///
+    /// # Bastion::supervisor(|supervisor| {
+    /// #    supervisor.children(|children| {
+    /// // attach a named distributor to the children
+    /// children
+    /// #        .with_redundancy(1)
+    ///     .with_distributor(Distributor::named("my distributor"))
+    ///     .with_exec(|ctx: BastionContext| {
+    ///        async move {
+    ///            loop {
+    ///                // The message handler needs an `on_question` section
+    ///                // that matches the `question` you're going to send,
+    ///                // and that will reply with the Type the request expects.
+    ///                // In our example, we ask a `&str` question, and expect a `bool` reply.                    
+    ///                MessageHandler::new(ctx.recv().await?)
+    ///                    .on_question(|message: &str, sender| {
+    ///                        if message == "is it raining today?" {
+    ///                            sender.reply(true).unwrap();
+    ///                        }
+    ///                    });
+    ///            }
+    ///            Ok(())
+    ///        }
+    ///     })
+    /// #   })
+    /// # });
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// let reply: Result<String, SendError> = distributor
+    ///     .request("is it raining today?")
+    ///     .await
+    ///     .expect("couldn't receive reply");
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn request<R: Message>(
+        &self,
+        question: impl Message,
+    ) -> oneshot::Receiver<Result<R, SendError>> {
+        let (sender, receiver) = oneshot::channel();
+        let s = *self;
+        spawn!(async move {
+            match SYSTEM.dispatcher().ask(s, question) {
+                Ok(response) => match response.await {
+                    Ok(message) => {
+                        let message_to_send = MessageHandler::new(message)
+                            .on_tell(|reply: R, _| Ok(reply))
+                            .on_fallback(|_, _| {
+                                Err(SendError::Other(anyhow::anyhow!(
+                                    "received a message with the wrong type"
+                                )))
+                            });
+                        let _ = sender.send(message_to_send);
+                    }
+                    Err(e) => {
+                        let _ = sender.send(Err(SendError::Other(anyhow::anyhow!(
+                            "couldn't receive reply: {:?}",
+                            e
+                        ))));
+                    }
+                },
+                Err(error) => {
+                    let _ = sender.send(Err(error));
+                }
+            };
+        });
+
+        receiver
+    }
+
+    /// Ask a question to a recipient attached to the `Distributor`
+    /// and wait for a reply.
+    ///
+    /// this is the sync variant of the `request` function, backed by a futures::channel::oneshot
+    /// # Example
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// # Bastion::start();
+    /// # Bastion::supervisor(|supervisor| {
+    /// #    supervisor.children(|children| {
+    /// // attach a named distributor to the children
+    /// children
+    /// #        .with_redundancy(1)
+    ///     .with_distributor(Distributor::named("my distributor"))
+    ///     .with_exec(|ctx: BastionContext| {
+    ///        async move {
+    ///            loop {
+    ///                // The message handler needs an `on_question` section
+    ///                // that matches the `question` you're going to send,
+    ///                // and that will reply with the Type the request expects.
+    ///                // In our example, we ask a `&str` question, and expect a `bool` reply.                    
+    ///                MessageHandler::new(ctx.recv().await?)
+    ///                    .on_question(|message: &str, sender| {
+    ///                        if message == "is it raining today?" {
+    ///                            sender.reply(true).unwrap();
+    ///                        }
+    ///                    });
+    ///            }
+    ///            Ok(())
+    ///        }
+    ///     })
+    /// #   })
+    /// # });
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// let reply: Result<bool, SendError> = distributor
+    ///    .request_sync("is it raining today?")
+    ///    .recv()
+    ///    .expect("couldn't receive reply"); // Ok(true)
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn request_sync<R: Message>(
+        &self,
+        question: impl Message,
+    ) -> Receiver<Result<R, SendError>> {
+        let (sender, receiver) = channel();
+        let s = *self;
+        spawn!(async move {
+            match SYSTEM.dispatcher().ask(s, question) {
+                Ok(response) => {
+                    if let Ok(message) = response.await {
+                        let message_to_send = MessageHandler::new(message)
+                            .on_tell(|reply: R, _| Ok(reply))
+                            .on_fallback(|_, _| {
+                                Err(SendError::Other(anyhow::anyhow!(
+                                    "received a message with the wrong type"
+                                )))
+                            });
+                        let _ = sender.send(message_to_send);
+                    } else {
+                        let _ = sender.send(Err(SendError::Other(anyhow::anyhow!(
+                            "couldn't receive reply"
+                        ))));
+                    }
+                }
+                Err(error) => {
+                    let _ = sender.send(Err(error));
+                }
+            };
+        });
+
+        receiver
+    }
+
+    /// Ask a question to a recipient attached to the `Distributor`
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// # Bastion::supervisor(|supervisor| {
+    /// #    supervisor.children(|children| {
+    ///     children
+    ///         .with_redundancy(1)
+    ///         .with_distributor(Distributor::named("my distributor"))
+    ///         .with_exec(|ctx: BastionContext| { // ...
+    /// #           async move {
+    /// #               loop {
+    /// #                   let _: Option<SignedMessage> = ctx.try_recv().await;
+    /// #               }
+    /// #               Ok(())
+    /// #           }
+    ///         })
+    /// #    })
+    /// # });
+    /// #
+    /// # Bastion::start();
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// let answer: Answer = distributor.ask_one("hello?").expect("couldn't send question");
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn ask_one(&self, question: impl Message) -> Result<Answer, SendError> {
+        SYSTEM.dispatcher().ask(*self, question)
+    }
+
+    /// Ask a question to all recipients attached to the `Distributor`
+    ///
+    /// Requires a `Message` that implements `Clone`. (it will be cloned and passed to each recipient)
+    /// # Example
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// # Bastion::supervisor(|supervisor| {
+    /// #    supervisor.children(|children| {
+    /// #    children
+    /// #        .with_redundancy(1)
+    /// #        .with_distributor(Distributor::named("my distributor"))
+    /// #        .with_exec(|ctx: BastionContext| {
+    /// #           async move {
+    /// #               loop {
+    /// #                   let _: Option<SignedMessage> = ctx.try_recv().await;
+    /// #               }
+    /// #               Ok(())
+    /// #           }
+    /// #        })
+    /// #    })
+    /// # });
+    /// #
+    /// # Bastion::start();
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// let answer: Vec<Answer> = distributor.ask_everyone("hello?".to_string()).expect("couldn't send question");
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn ask_everyone(&self, question: impl Message + Clone) -> Result<Vec<Answer>, SendError> {
+        SYSTEM.dispatcher().ask_everyone(*self, question)
+    }
+
+    /// Send a Message to a recipient attached to the `Distributor`
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// # Bastion::supervisor(|supervisor| {
+    /// #    supervisor.children(|children| {
+    /// #    children
+    /// #        .with_redundancy(1)
+    /// #        .with_distributor(Distributor::named("my distributor"))
+    /// #        .with_exec(|ctx: BastionContext| {
+    /// #           async move {
+    /// #               loop {
+    /// #                   let _: Option<SignedMessage> = ctx.try_recv().await;
+    /// #               }
+    /// #               Ok(())
+    /// #           }
+    /// #        })
+    /// #    })
+    /// # });
+    /// #
+    /// # Bastion::start();
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// let answer: () = distributor.tell_one("hello?").expect("couldn't send question");
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn tell_one(&self, message: impl Message) -> Result<(), SendError> {
+        SYSTEM.dispatcher().tell(*self, message)
+    }
+
+    /// Send a Message to each recipient attached to the `Distributor`
+    ///
+    /// Requires a `Message` that implements `Clone`. (it will be cloned and passed to each recipient)
+    /// # Example
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// # Bastion::supervisor(|supervisor| {
+    /// #    supervisor.children(|children| {
+    /// #    children
+    /// #        .with_redundancy(1)
+    /// #        .with_distributor(Distributor::named("my distributor"))
+    /// #        .with_exec(|ctx: BastionContext| {
+    /// #           async move {
+    /// #               loop {
+    /// #                   let _: Option<SignedMessage> = ctx.try_recv().await;
+    /// #               }
+    /// #               Ok(())
+    /// #           }
+    /// #        })
+    /// #    })
+    /// # });
+    /// #
+    /// # Bastion::start();
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// let answer: () = distributor.tell_one("hello?").expect("couldn't send question");
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn tell_everyone(&self, message: impl Message + Clone) -> Result<Vec<()>, SendError> {
+        SYSTEM.dispatcher().tell_everyone(*self, message)
+    }
+
+    /// subscribe a `ChildRef` to the named `Distributor`
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// # let children =
+    /// #    Bastion::children(|children| {
+    /// #    children
+    /// #        .with_redundancy(1)
+    /// #        .with_distributor(Distributor::named("my distributor"))
+    /// #        .with_exec(|ctx: BastionContext| {
+    /// #           async move {
+    /// #               loop {
+    /// #                   let _: Option<SignedMessage> = ctx.try_recv().await;
+    /// #               }
+    /// #               Ok(())
+    /// #           }
+    /// #        })
+    /// # }).unwrap();
+    /// #
+    /// # Bastion::start();
+    /// #
+    /// let child_ref = children.elems()[0].clone();
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// // child_ref will now be elligible to receive messages dispatched through distributor
+    /// distributor.subscribe(child_ref).expect("couldn't subscribe child to distributor");
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn subscribe(&self, child_ref: ChildRef) -> AnyResult<()> {
+        SYSTEM.dispatcher().register_recipient(self, child_ref)
+    }
+
+    /// unsubscribe a `ChildRef` to the named `Distributor`
+    ///
+    /// ```no_run
+    /// # use bastion::prelude::*;
+    /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
+    /// # Bastion::init();
+    /// # let children =
+    /// #    Bastion::children(|children| {
+    /// #    children
+    /// #        .with_redundancy(1)
+    /// #        .with_distributor(Distributor::named("my distributor"))
+    /// #        .with_exec(|ctx: BastionContext| {
+    /// #           async move {
+    /// #               loop {
+    /// #                   let _: Option<SignedMessage> = ctx.try_recv().await;
+    /// #               }
+    /// #               Ok(())
+    /// #           }
+    /// #        })
+    /// # }).unwrap();
+    /// #
+    /// # Bastion::start();
+    /// #
+    /// let child_ref = children.elems()[0].clone();
+    ///
+    /// let distributor = Distributor::named("my distributor");
+    ///
+    /// // child_ref will not receive messages dispatched through the distributor anymore
+    /// distributor.unsubscribe(child_ref).expect("couldn't unsubscribe child to distributor");
+    ///
+    /// # Bastion::stop();
+    /// # Bastion::block_until_stopped();
+    /// # }
+    /// ```
+    pub fn unsubscribe(&self, child_ref: ChildRef) -> AnyResult<()> {
+        let global_dispatcher = SYSTEM.dispatcher();
+        global_dispatcher.remove_recipient(&vec![*self], child_ref)
+    }
+
+    pub(crate) fn interned(&self) -> &Spur {
+        &self.0
+    }
+}
+
+#[cfg(test)]
+mod distributor_tests {
+    use crate::prelude::*;
+    use futures::channel::mpsc::channel;
+    use futures::{SinkExt, StreamExt};
+
+    const TEST_DISTRIBUTOR: &str = "test distributor";
+    const SUBSCRIBE_TEST_DISTRIBUTOR: &str = "subscribe test";
+
+    #[cfg(feature = "tokio-runtime")]
+    #[tokio::test]
+    async fn test_tokio_distributor() {
+        blocking!({
+            run_tests();
+        });
+    }
+
+    #[cfg(not(feature = "tokio-runtime"))]
+    #[test]
+    fn distributor_tests() {
+        run_tests();
+    }
+
+    fn run_tests() {
+        setup();
+
+        test_tell();
+        test_ask();
+        test_request();
+        test_subscribe();
+    }
+
+    fn test_subscribe() {
+        let temp_distributor = Distributor::named("temp distributor");
+
+        assert!(
+            temp_distributor.tell_one("hello!").is_err(),
+            "should not be able to send message to an empty distributor"
+        );
+
+        let one_child: ChildRef = run!(async {
+            Distributor::named(SUBSCRIBE_TEST_DISTRIBUTOR)
+                .request(())
+                .await
+                .unwrap()
+                .unwrap()
+        });
+        temp_distributor.subscribe(one_child.clone()).unwrap();
+
+        temp_distributor
+            .tell_one("hello!")
+            .expect("should be able to send message a distributor that has a subscriber");
+
+        temp_distributor.unsubscribe(one_child).unwrap();
+
+        assert!(
+            temp_distributor.tell_one("hello!").is_err(),
+            "should not be able to send message to a distributor who's sole subscriber unsubscribed"
+        );
+    }
+
+    fn test_tell() {
+        let test_distributor = Distributor::named(TEST_DISTRIBUTOR);
+
+        test_distributor
+            .tell_one("don't panic and carry a towel")
+            .unwrap();
+
+        let sent = test_distributor
+            .tell_everyone("so long, and thanks for all the fish")
+            .unwrap();
+
+        assert_eq!(
+            5,
+            sent.len(),
+            "test distributor is supposed to have 5 children"
+        );
+    }
+
+    fn test_ask() {
+        let test_distributor = Distributor::named(TEST_DISTRIBUTOR);
+
+        let question: String =
+            "What is the answer to life, the universe and everything?".to_string();
+
+        run!(async {
+            let answer = test_distributor.ask_one(question.clone()).unwrap();
+            MessageHandler::new(answer.await.unwrap())
+                .on_tell(|answer: u8, _| {
+                    assert_eq!(42, answer);
+                })
+                .on_fallback(|unknown, _sender_addr| {
+                    panic!("unknown message\n {:?}", unknown);
+                });
+        });
+
+        run!(async {
+            let answers = test_distributor.ask_everyone(question.clone()).unwrap();
+            assert_eq!(
+                5,
+                answers.len(),
+                "test distributor is supposed to have 5 children"
+            );
+            let meanings = futures::future::join_all(answers.into_iter().map(|answer| async {
+                MessageHandler::new(answer.await.unwrap())
+                    .on_tell(|answer: u8, _| {
+                        assert_eq!(42, answer);
+                        answer
+                    })
+                    .on_fallback(|unknown, _sender_addr| {
+                        panic!("unknown message\n {:?}", unknown);
+                    })
+            }))
+            .await;
+
+            assert_eq!(
+                42 * 5,
+                meanings.iter().sum::<u8>(),
+                "5 children returning 42 should sum to 42 * 5"
+            );
+        });
+    }
+
+    fn test_request() {
+        let test_distributor = Distributor::named(TEST_DISTRIBUTOR);
+
+        let question: String =
+            "What is the answer to life, the universe and everything?".to_string();
+
+        run!(async {
+            let answer: u8 = test_distributor
+                .request(question.clone())
+                .await
+                .unwrap()
+                .unwrap();
+            assert_eq!(42, answer);
+        });
+
+        let answer_sync: u8 = test_distributor
+            .request_sync(question)
+            .recv()
+            .unwrap()
+            .unwrap();
+
+        assert_eq!(42, answer_sync);
+    }
+
+    fn setup() {
+        Bastion::init();
+        Bastion::start();
+
+        const NUM_CHILDREN: usize = 5;
+
+        // This channel and the use of callbacks will allow us to know when all of the children are spawned.
+        let (sender, receiver) = channel(NUM_CHILDREN);
+
+        Bastion::supervisor(|supervisor| {
+            let test_ready = sender.clone();
+            let subscribe_test_ready = sender.clone();
+            supervisor
+                .children(|children| {
+                    children
+                        .with_redundancy(NUM_CHILDREN)
+                        .with_distributor(Distributor::named(TEST_DISTRIBUTOR))
+                        .with_callbacks(Callbacks::new().with_after_start(move || {
+                            let mut test_ready = test_ready.clone();
+                            spawn!(async move { test_ready.send(()).await });
+                        }))
+                        .with_exec(|ctx| async move {
+                            loop {
+                                let child_ref = ctx.current().clone();
+                                MessageHandler::new(ctx.recv().await?)
+                                    .on_question(|_: String, sender| {
+                                        let _ = sender.reply(42_u8);
+                                    })
+                                    // send your child ref
+                                    .on_question(|_: (), sender| {
+                                        let _ = sender.reply(child_ref);
+                                    });
+                            }
+                        })
+                    // Subscribe / unsubscribe tests
+                })
+                .children(|children| {
+                    children
+                        .with_distributor(Distributor::named(SUBSCRIBE_TEST_DISTRIBUTOR))
+                        .with_callbacks(Callbacks::new().with_after_start(move || {
+                            let mut subscribe_test_ready = subscribe_test_ready.clone();
+                            spawn!(async move { subscribe_test_ready.send(()).await });
+                        }))
+                        .with_exec(|ctx| async move {
+                            loop {
+                                let child_ref = ctx.current().clone();
+                                MessageHandler::new(ctx.recv().await?).on_question(
+                                    |_: (), sender| {
+                                        let _ = sender.reply(child_ref);
+                                    },
+                                );
+                            }
+                        })
+                })
+        })
+        .unwrap();
+
+        // Wait until the children have spawned
+        run!(async {
+            // NUM_CHILDREN for the test distributor group,
+            // 1 for the subscribe test group
+            receiver.take(NUM_CHILDREN + 1).collect::<Vec<_>>().await;
+        });
+    }
+}
diff --git a/src/bastion/src/envelope.rs b/src/bastion/src/envelope.rs
index a476ed69..4b7033e1 100644
--- a/src/bastion/src/envelope.rs
+++ b/src/bastion/src/envelope.rs
@@ -3,9 +3,9 @@
 //! and instruct Bastion how to send messages back to them
 
 use crate::broadcast::Sender;
+use crate::global_system::SYSTEM;
 use crate::message::{BastionMessage, Message, Msg};
 use crate::path::BastionPath;
-use crate::system::SYSTEM;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -22,6 +22,18 @@ pub(crate) struct Envelope {
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 /// Bastion::children(|children| {
@@ -37,6 +49,7 @@ pub(crate) struct Envelope {
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 pub struct SignedMessage {
     pub(crate) msg: Msg,
@@ -60,6 +73,18 @@ impl SignedMessage {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::children(|children| {
@@ -75,6 +100,7 @@ impl SignedMessage {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn signature(&self) -> &RefAddr {
         &self.sign
@@ -89,6 +115,18 @@ impl SignedMessage {
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 /// Bastion::children(|children| {
@@ -106,6 +144,7 @@ impl SignedMessage {
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 pub struct RefAddr {
     path: Arc<BastionPath>,
@@ -134,7 +173,18 @@ impl RefAddr {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     ///     # let children_ref = Bastion::children(|children| children).unwrap();
@@ -174,7 +224,18 @@ impl RefAddr {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     ///     # let children_ref = Bastion::children(|children| children).unwrap();
diff --git a/src/bastion/src/error.rs b/src/bastion/src/error.rs
new file mode 100644
index 00000000..fcee1404
--- /dev/null
+++ b/src/bastion/src/error.rs
@@ -0,0 +1,94 @@
+//!
+//! Describes the error types that may happen within bastion.
+//! Given Bastion has a let it crash strategy, most error aren't noticeable.
+//! A ReceiveError may however be raised when calling try_recv() or try_recv_timeout()
+//! More errors may happen in the future.
+
+use crate::envelope::Envelope;
+use crate::message::Msg;
+use crate::system::STRING_INTERNER;
+use crate::{distributor::Distributor, message::BastionMessage};
+use futures::channel::mpsc::TrySendError;
+use std::fmt::Debug;
+use std::result;
+use std::result;
+use std::time::Duration;
+use thiserror::Error;
+
+pub type BastionResult<T> = result::Result<T, BastionError>;
+
+// TODO [igni]: make it one bastionerror enum and merge everything
+
+#[derive(Debug)]
+pub enum BastionError {
+    Receive(ReceiveError),
+    ChanSend(String),
+    ChanRecv(String),
+    UnackedMessage,
+}
+
+#[derive(Debug)]
+/// These errors happen
+/// when [`try_recv`] or [`try_recv_timeout`] are invoked
+///
+/// [`try_recv`]: crate::context::BastionContext::try_recv
+/// [`try_recv_timeout`]: crate::context::BastionContext::try_recv_timeout
+pub enum ReceiveError {
+    /// We didn't receive a message on time
+    Timeout(Duration),
+    /// Generic error. Not used yet
+    Other,
+}
+
+#[derive(Error, Debug)]
+/// `SendError`s occur when a message couldn't be dispatched through a distributor
+pub enum SendError {
+    #[error("couldn't send message. Channel Disconnected.")]
+    /// Channel has been closed before we could send a message
+    Disconnected(Msg),
+    #[error("couldn't send message. Channel is Full.")]
+    /// Channel is full, can't send a message
+    Full(Msg),
+    #[error("couldn't send a message I should have not sent. {0}")]
+    /// This error is returned when we try to send a message
+    /// that is not a BastionMessage::Message variant
+    Other(anyhow::Error),
+    #[error("No available Distributor matching {0}")]
+    /// The distributor we're trying to dispatch messages to is not registered in the system
+    NoDistributor(String),
+    #[error("Distributor has 0 Recipients")]
+    /// The distributor we're trying to dispatch messages to has no recipients
+    EmptyRecipient,
+}
+
+impl From<TrySendError<Envelope>> for SendError {
+    fn from(tse: TrySendError<Envelope>) -> Self {
+        let is_disconnected = tse.is_disconnected();
+        match tse.into_inner().msg {
+            BastionMessage::Message(msg) => {
+                if is_disconnected {
+                    Self::Disconnected(msg)
+                } else {
+                    Self::Full(msg)
+                }
+            }
+            other => Self::Other(anyhow::anyhow!("{:?}", other)),
+        }
+    }
+}
+
+impl From<Distributor> for SendError {
+    fn from(distributor: Distributor) -> Self {
+        Self::NoDistributor(STRING_INTERNER.resolve(distributor.interned()).to_string())
+    }
+}
+
+#[derive(Error, Debug)]
+pub enum BastionError {
+    #[error("The message cannot be sent via the channel. Reason: {0}")]
+    ChanSend(String),
+    #[error("The message cannot be received from the channel. Reason: {0}")]
+    ChanRecv(String),
+    #[error("Before requesting a next message the previous message must be acked.")]
+    UnackedMessage,
+}
diff --git a/src/bastion/src/errors.rs b/src/bastion/src/errors.rs
index e2c9144e..b1415da0 100644
--- a/src/bastion/src/errors.rs
+++ b/src/bastion/src/errors.rs
@@ -1,7 +1,83 @@
+//!
+//! Describes the error types that may happen within bastion.
+//! Given Bastion has a let it crash strategy, most error aren't noticeable.
+//! A ReceiveError may however be raised when calling try_recv() or try_recv_timeout()
+//! More errors may happen in the future.
+
+use crate::envelope::Envelope;
+use crate::global_system::STRING_INTERNER;
+use crate::message::Msg;
+use crate::{distributor::Distributor, message::BastionMessage};
+use futures::channel::mpsc::TrySendError;
+use std::fmt::Debug;
+use std::result;
 use std::time::Duration;
+use thiserror::Error;
+
+pub type BastionResult<T> = result::Result<T, BastionError>;
+
+// TODO [igni]: make it one bastionerror enum and merge everything
+
+#[derive(Debug)]
+pub enum BastionError {
+    Receive(ReceiveError),
+    ChanSend(String),
+    ChanRecv(String),
+    UnackedMessage,
+}
 
 #[derive(Debug)]
+/// These errors happen
+/// when [`try_recv`] or [`try_recv_timeout`] are invoked
+///
+/// [`try_recv`]: crate::context::BastionContext::try_recv
+/// [`try_recv_timeout`]: crate::context::BastionContext::try_recv_timeout
 pub enum ReceiveError {
+    /// We didn't receive a message on time
     Timeout(Duration),
+    /// Generic error. Not used yet
     Other,
 }
+
+#[derive(Error, Debug)]
+/// `SendError`s occur when a message couldn't be dispatched through a distributor
+pub enum SendError {
+    #[error("couldn't send message. Channel Disconnected.")]
+    /// Channel has been closed before we could send a message
+    Disconnected(Msg),
+    #[error("couldn't send message. Channel is Full.")]
+    /// Channel is full, can't send a message
+    Full(Msg),
+    #[error("couldn't send a message I should have not sent. {0}")]
+    /// This error is returned when we try to send a message
+    /// that is not a BastionMessage::Message variant
+    Other(anyhow::Error),
+    #[error("No available Distributor matching {0}")]
+    /// The distributor we're trying to dispatch messages to is not registered in the system
+    NoDistributor(String),
+    #[error("Distributor has 0 Recipients")]
+    /// The distributor we're trying to dispatch messages to has no recipients
+    EmptyRecipient,
+}
+
+impl From<TrySendError<Envelope>> for SendError {
+    fn from(tse: TrySendError<Envelope>) -> Self {
+        let is_disconnected = tse.is_disconnected();
+        match tse.into_inner().msg {
+            BastionMessage::Message(msg) => {
+                if is_disconnected {
+                    Self::Disconnected(msg)
+                } else {
+                    Self::Full(msg)
+                }
+            }
+            other => Self::Other(anyhow::anyhow!("{:?}", other)),
+        }
+    }
+}
+
+impl From<Distributor> for SendError {
+    fn from(distributor: Distributor) -> Self {
+        Self::NoDistributor(STRING_INTERNER.resolve(distributor.interned()).to_string())
+    }
+}
diff --git a/src/bastion/src/executor.rs b/src/bastion/src/executor.rs
index 7e6d0c1e..cd8ef5cd 100644
--- a/src/bastion/src/executor.rs
+++ b/src/bastion/src/executor.rs
@@ -10,10 +10,23 @@ use std::future::Future;
 /// # Example
 /// ```
 /// # use std::{thread, time};
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// use bastion::executor::blocking;
 /// let task = blocking(async move {
 ///     thread::sleep(time::Duration::from_millis(3000));
 /// });
+/// # }
 /// ```
 pub fn blocking<F, R>(future: F) -> RecoverableHandle<R>
 where
@@ -29,6 +42,18 @@ where
 /// # Example
 /// ```
 /// # use bastion::prelude::*;
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// use bastion::executor::run;
 /// let future1 = async move {
 ///     123
@@ -45,6 +70,7 @@ where
 ///
 /// let result = run(future2);
 /// assert_eq!(result, 5);
+/// # }
 /// ```
 pub fn run<F, T>(future: F) -> T
 where
@@ -58,11 +84,24 @@ where
 /// # Example
 /// ```
 /// # use bastion::prelude::*;
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// use bastion::executor::{spawn, run};
 /// let handle = spawn(async {
 ///     panic!("test");
 /// });
 /// run(handle);
+/// # }
 /// ```
 pub fn spawn<F, T>(future: F) -> RecoverableHandle<T>
 where
diff --git a/src/bastion/src/system.rs b/src/bastion/src/global_system.rs
similarity index 98%
rename from src/bastion/src/system.rs
rename to src/bastion/src/global_system.rs
index 69f229b2..9ff74f15 100644
--- a/src/bastion/src/system.rs
+++ b/src/bastion/src/global_system.rs
@@ -12,15 +12,17 @@ use futures::prelude::*;
 use futures::stream::FuturesUnordered;
 use futures::{pending, poll};
 use fxhash::{FxHashMap, FxHashSet};
-use lazy_static::lazy_static;
+use lasso::ThreadedRodeo;
 use lightproc::prelude::*;
+use once_cell::sync::Lazy;
 use std::sync::{Arc, Condvar, Mutex};
 use std::task::Poll;
 use tracing::{debug, error, info, trace, warn};
 
-lazy_static! {
-    pub(crate) static ref SYSTEM: GlobalSystem = System::init();
-}
+pub(crate) static STRING_INTERNER: Lazy<Arc<ThreadedRodeo>> =
+    Lazy::new(|| Arc::new(Default::default()));
+
+pub(crate) static SYSTEM: Lazy<GlobalSystem> = Lazy::new(System::init);
 
 pub(crate) struct GlobalSystem {
     sender: Sender,
diff --git a/src/bastion/src/lib.rs b/src/bastion/src/lib.rs
index a41955a0..c79eae09 100644
--- a/src/bastion/src/lib.rs
+++ b/src/bastion/src/lib.rs
@@ -65,11 +65,13 @@ pub use self::config::Config;
 #[macro_use]
 mod macros;
 
+mod actor;
 mod bastion;
 mod broadcast;
 mod callbacks;
 mod child;
 mod config;
+mod global_system;
 mod system;
 
 pub mod child_ref;
@@ -81,14 +83,18 @@ pub mod envelope;
 pub mod executor;
 #[cfg(not(target_os = "windows"))]
 pub mod io;
+mod mailbox;
 pub mod message;
 pub mod path;
 #[cfg(feature = "scaling")]
 pub mod resizer;
+mod routing;
 pub mod supervisor;
 
 pub mod errors;
 
+pub mod distributor;
+
 distributed_api! {
     // pub mod dist_messages;
     pub mod distributed;
@@ -108,11 +114,12 @@ pub mod prelude {
         BroadcastTarget, DefaultDispatcherHandler, Dispatcher, DispatcherHandler, DispatcherMap,
         DispatcherType, NotificationType,
     };
+    pub use crate::distributor::Distributor;
     pub use crate::envelope::{RefAddr, SignedMessage};
     pub use crate::errors::*;
     #[cfg(not(target_os = "windows"))]
     pub use crate::io::*;
-    pub use crate::message::{Answer, AnswerSender, Message, Msg};
+    pub use crate::message::{Answer, AnswerSender, Message, MessageHandler, Msg};
     pub use crate::msg;
     pub use crate::path::{BastionPath, BastionPathElement};
     #[cfg(feature = "scaling")]
diff --git a/src/bastion/src/macros.rs b/src/bastion/src/macros.rs
index 68d068e9..d577075e 100644
--- a/src/bastion/src/macros.rs
+++ b/src/bastion/src/macros.rs
@@ -8,7 +8,18 @@
 ///
 /// ```
 /// # use bastion::prelude::*;
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// let children = children! {
 ///     // the default redundancy is 1
 ///     redundancy: 100,
@@ -133,7 +144,18 @@ macro_rules! children {
 /// # Example
 /// ```
 /// # use bastion::prelude::*;
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// let sp = supervisor! {
 ///     callbacks: Callbacks::default(),
 ///     strategy: SupervisionStrategy::OneForAll,
@@ -189,7 +211,18 @@ macro_rules! supervisor {
 /// # use std::{thread, time};
 /// # use lightproc::proc_stack::ProcStack;
 /// # use bastion::prelude::*;
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// let task = blocking! {
 ///     thread::sleep(time::Duration::from_millis(3000));
 /// };
@@ -211,7 +244,18 @@ macro_rules! blocking {
 /// # Example
 /// ```
 /// # use bastion::prelude::*;
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// let future1 = async move {
 ///     123
 /// };
@@ -245,7 +289,18 @@ macro_rules! run {
 /// # Example
 /// ```
 /// # use bastion::prelude::*;
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// let handle = spawn! {
 ///     panic!("test");
 /// };
diff --git a/src/bastion/src/mailbox/envelope.rs b/src/bastion/src/mailbox/envelope.rs
new file mode 100644
index 00000000..726011ec
--- /dev/null
+++ b/src/bastion/src/mailbox/envelope.rs
@@ -0,0 +1,63 @@
+use std::fmt::{self, Debug, Formatter};
+
+use crate::actor::actor_ref::ActorRef;
+use crate::mailbox::message::MessageType;
+use crate::mailbox::traits::TypedMessage;
+
+/// Struct that represents an incoming message in the actor's mailbox.
+#[derive(Clone)]
+pub struct Envelope<T>
+where
+    T: TypedMessage,
+{
+    /// The sending side of a channel. In actor's world
+    /// represented is a message sender. Can be used
+    /// for acking message when it possible.
+    sender: Option<ActorRef>,
+    /// An actual data sent by the channel
+    message: T,
+    /// Message type that helps to figure out how to deliver message
+    /// and how to ack it after the processing.
+    message_type: MessageType,
+}
+
+impl<T> Envelope<T>
+where
+    T: TypedMessage,
+{
+    /// Create a message with the given sender and inner data.
+    pub fn new(sender: Option<ActorRef>, message: T, message_type: MessageType) -> Self {
+        Envelope {
+            sender,
+            message,
+            message_type,
+        }
+    }
+
+    /// Returns a message type. Can be use for pattern matching and filtering
+    /// incoming message from other actors.
+    pub fn message_type(&self) -> MessageType {
+        self.message_type.clone()
+    }
+
+    /// Sends a confirmation to the message sender.
+    pub(crate) async fn ack(&self) {
+        match self.message_type {
+            MessageType::Ack => unimplemented!(),
+            MessageType::Broadcast => unimplemented!(),
+            MessageType::Tell => unimplemented!(),
+        }
+    }
+}
+
+impl<T> Debug for Envelope<T>
+where
+    T: TypedMessage,
+{
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        fmt.debug_struct("Message")
+            .field("message", &self.message)
+            .field("message_type", &self.message_type)
+            .finish()
+    }
+}
diff --git a/src/bastion/src/mailbox/message.rs b/src/bastion/src/mailbox/message.rs
new file mode 100644
index 00000000..9007dbf0
--- /dev/null
+++ b/src/bastion/src/mailbox/message.rs
@@ -0,0 +1,14 @@
+/// Enum that provides information what type of the message
+/// being sent through the channel.
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum MessageType {
+    /// A message type that requires sending a confirmation to the
+    /// sender after begin the processing stage.
+    Ack,
+    /// A message that can be broadcasted (e.g. via system dispatchers). This
+    /// message type doesn't require to be acked from the receiver's side.
+    Broadcast,
+    /// A message was sent directly and doesn't require confirmation for the
+    /// delivery and being processed.
+    Tell,
+}
diff --git a/src/bastion/src/mailbox/mod.rs b/src/bastion/src/mailbox/mod.rs
new file mode 100644
index 00000000..7afeabb6
--- /dev/null
+++ b/src/bastion/src/mailbox/mod.rs
@@ -0,0 +1,166 @@
+mod envelope;
+mod state;
+
+pub mod message;
+pub mod traits;
+
+use std::sync::atomic::AtomicBool;
+use std::sync::Arc;
+
+use async_channel::{unbounded, Receiver, Sender};
+
+use crate::errors::{BastionError, BastionResult};
+use crate::mailbox::envelope::Envelope;
+use crate::mailbox::state::MailboxState;
+use crate::mailbox::traits::TypedMessage;
+
+/// Struct that represents a message sender.
+#[derive(Clone)]
+pub struct MailboxTx<T>
+where
+    T: TypedMessage,
+{
+    /// Indicated the transmitter part of the actor's channel
+    /// which is using for passing messages.
+    tx: Sender<Envelope<T>>,
+    /// A field for checks that the message has been delivered to
+    /// the specific actor.
+    scheduled: Arc<AtomicBool>,
+}
+
+impl<T> MailboxTx<T>
+where
+    T: TypedMessage,
+{
+    /// Return a new instance of MailboxTx that indicates sender.
+    pub(crate) fn new(tx: Sender<Envelope<T>>) -> Self {
+        let scheduled = Arc::new(AtomicBool::new(false));
+        MailboxTx { tx, scheduled }
+    }
+
+    /// Send the message to the actor by the channel.
+    pub fn try_send(&self, msg: Envelope<T>) -> BastionResult<()> {
+        self.tx
+            .try_send(msg)
+            .map_err(|e| BastionError::ChanSend(e.to_string()))
+    }
+}
+
+/// A struct that holds everything related to messages that can be
+/// retrieved from other actors. Each actor holds two queues: one for
+/// messages that come from user-defined actors, and another for
+/// internal messaging that must be handled separately.
+///
+/// For each used queue, mailbox always holds the latest requested message
+/// by a user, to guarantee that the message won't be lost if something
+/// happens wrong.
+#[derive(Clone)]
+pub struct Mailbox<T>
+where
+    T: TypedMessage,
+{
+    /// User guardian sender
+    user_tx: MailboxTx<T>,
+    /// User guardian receiver
+    user_rx: Receiver<Envelope<T>>,
+    /// System guardian receiver
+    system_rx: Receiver<Envelope<T>>,
+    /// The current processing message, received from the
+    /// latest call to the user's queue
+    last_user_message: Option<Envelope<T>>,
+    /// The current processing message, received from the
+    /// latest call to the system's queue
+    last_system_message: Option<Envelope<T>>,
+    /// Mailbox state machine
+    state: Arc<MailboxState>,
+}
+
+// TODO: Add calls with recv with timeout
+impl<T> Mailbox<T>
+where
+    T: TypedMessage,
+{
+    /// Creates a new mailbox for the actor.
+    pub(crate) fn new(system_rx: Receiver<Envelope<T>>) -> Self {
+        let (tx, user_rx) = unbounded();
+        let user_tx = MailboxTx::new(tx);
+        let last_user_message = None;
+        let last_system_message = None;
+        let state = Arc::new(MailboxState::new());
+
+        Mailbox {
+            user_tx,
+            user_rx,
+            system_rx,
+            last_user_message,
+            last_system_message,
+            state,
+        }
+    }
+
+    /// Forced receive message from user queue
+    pub async fn recv(&mut self) -> Envelope<T> {
+        let message = self
+            .user_rx
+            .recv()
+            .await
+            .map_err(|e| BastionError::ChanRecv(e.to_string()))
+            .unwrap();
+
+        self.last_user_message = Some(message);
+        self.last_user_message.clone().unwrap()
+    }
+
+    /// Try receiving message from user queue
+    pub async fn try_recv(&mut self) -> BastionResult<Envelope<T>> {
+        if self.last_user_message.is_some() {
+            return Err(BastionError::UnackedMessage);
+        }
+
+        match self.user_rx.try_recv() {
+            Ok(message) => {
+                self.last_user_message = Some(message);
+                Ok(self.last_user_message.clone().unwrap())
+            }
+            Err(e) => Err(BastionError::ChanRecv(e.to_string())),
+        }
+    }
+
+    /// Forced receive message from system queue
+    pub async fn sys_recv(&mut self) -> Envelope<T> {
+        let message = self
+            .system_rx
+            .recv()
+            .await
+            .map_err(|e| BastionError::ChanRecv(e.to_string()))
+            .unwrap();
+
+        self.last_system_message = Some(message);
+        self.last_system_message.clone().unwrap()
+    }
+
+    /// Try receiving message from system queue
+    pub async fn try_sys_recv(&mut self) -> BastionResult<Envelope<T>> {
+        if self.last_system_message.is_some() {
+            return Err(BastionError::UnackedMessage);
+        }
+
+        match self.system_rx.try_recv() {
+            Ok(message) => {
+                self.last_system_message = Some(message);
+                Ok(self.last_system_message.clone().unwrap())
+            }
+            Err(e) => Err(BastionError::ChanRecv(e.to_string())),
+        }
+    }
+
+    /// Returns the last retrieved message from the user channel
+    pub async fn get_last_user_message(&self) -> Option<Envelope<T>> {
+        self.last_user_message.clone()
+    }
+
+    /// Returns the last retrieved message from the system channel
+    pub async fn get_last_system_message(&self) -> Option<Envelope<T>> {
+        self.last_system_message.clone()
+    }
+}
diff --git a/src/bastion/src/mailbox/state.rs b/src/bastion/src/mailbox/state.rs
new file mode 100644
index 00000000..c22c5bd2
--- /dev/null
+++ b/src/bastion/src/mailbox/state.rs
@@ -0,0 +1,106 @@
+use crossbeam::atomic::AtomicCell;
+
+// Mailbox state holder
+#[derive(Debug)]
+pub(crate) struct MailboxState {
+    inner: AtomicCell<InnerState>,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+/// An enum that specifies a lifecycle of the message that has
+/// been sent by the actor in the system.
+///
+/// The whole lifecycle of the message can be described by the
+/// next schema:
+/// ```ignore
+///
+///    +---- Message processed -----+
+///    ↓                            |
+/// Scheduled -> Sent -> Awaiting --+
+///               ↑           |
+///               +-- Retry --+
+///
+/// ```
+enum InnerState {
+    /// Message has been scheduled to delivery
+    Scheduled,
+    /// Message has been sent to destination
+    Sent,
+    /// Ack has currently been awaited
+    Awaiting,
+}
+
+impl MailboxState {
+    pub(crate) fn new() -> Self {
+        MailboxState {
+            inner: AtomicCell::new(InnerState::Scheduled),
+        }
+    }
+
+    pub(crate) fn set_scheduled(&self) {
+        self.inner.store(InnerState::Scheduled)
+    }
+
+    pub(crate) fn set_sent(&self) {
+        self.inner.store(InnerState::Sent)
+    }
+
+    pub(crate) fn set_awaiting(&self) {
+        self.inner.store(InnerState::Awaiting)
+    }
+
+    pub(crate) fn is_scheduled(&self) -> bool {
+        self.inner.load() == InnerState::Scheduled
+    }
+
+    pub(crate) fn is_sent(&self) -> bool {
+        self.inner.load() == InnerState::Sent
+    }
+
+    pub(crate) fn is_awaiting(&self) -> bool {
+        self.inner.load() == InnerState::Awaiting
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::mailbox::state::MailboxState;
+
+    #[test]
+    fn test_normal_path() {
+        let state = MailboxState::new();
+
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_sent();
+        assert_eq!(state.is_sent(), true);
+
+        state.set_awaiting();
+        assert_eq!(state.is_awaiting(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+    }
+
+    #[test]
+    fn test_path_with_retry() {
+        let state = MailboxState::new();
+
+        assert_eq!(state.is_scheduled(), true);
+
+        state.set_sent();
+        assert_eq!(state.is_sent(), true);
+
+        state.set_awaiting();
+        assert_eq!(state.is_awaiting(), true);
+
+        state.set_sent();
+        assert_eq!(state.is_sent(), true);
+
+        state.set_awaiting();
+        assert_eq!(state.is_awaiting(), true);
+
+        state.set_scheduled();
+        assert_eq!(state.is_scheduled(), true);
+    }
+}
diff --git a/src/bastion/src/mailbox/traits.rs b/src/bastion/src/mailbox/traits.rs
new file mode 100644
index 00000000..c068800b
--- /dev/null
+++ b/src/bastion/src/mailbox/traits.rs
@@ -0,0 +1,13 @@
+use std::fmt::Debug;
+
+/// A trait that message needs to implement for typed actors (it is
+/// already automatically implemented but forces message to
+/// implement the following traits: [`Any`], [`Send`],
+/// [`Sync`] and [`Debug`]).
+///
+/// [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
+/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
+/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+/// [`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
+pub trait TypedMessage: Clone + Send + Debug + 'static {}
+impl<T> TypedMessage for T where T: Clone + Send + Debug + 'static {}
diff --git a/src/bastion/src/message.rs b/src/bastion/src/message.rs
index c1ccb914..688fab28 100644
--- a/src/bastion/src/message.rs
+++ b/src/bastion/src/message.rs
@@ -11,7 +11,7 @@ use crate::children::Children;
 use crate::context::{BastionId, ContextState};
 use crate::envelope::{RefAddr, SignedMessage};
 use crate::supervisor::{SupervisionStrategy, Supervisor};
-use async_mutex::Mutex;
+
 use futures::channel::oneshot::{self, Receiver};
 use std::any::{type_name, Any};
 use std::fmt::Debug;
@@ -26,20 +26,37 @@ use tracing::{debug, trace};
 /// implement the following traits: [`Any`], [`Send`],
 /// [`Sync`] and [`Debug`]).
 ///
+/// [`Any`]: std::any::Any
+/// [`Send`]: std::marker::Send
+/// [`Sync`]: std::marker::Sync
+/// [`Debug`]: std::fmt::Debug
+pub trait Message: Any + Send + Sync + Debug {}
+impl<T> Message for T where T: Any + Send + Sync + Debug {}
+
+/// A trait that message needs to implement for typed actors (it is
+/// already automatically implemented but forces message to
+/// implement the following traits: [`Any`], [`Send`],
+/// [`Sync`] and [`Debug`]).
+///
 /// [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
 /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
 /// [`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
-pub trait Message: Any + Send + Sync + Debug {}
-impl<T> Message for T where T: Any + Send + Sync + Debug {}
+pub trait TypedMessage: Clone + Send + Debug + 'static {}
+impl<T> TypedMessage for T where T: Clone + Send + Debug + 'static {}
 
+/// Allows to respond to questions.
+///
+/// This type features the [`respond`] method, that allows to respond to a
+/// question.
+///
+/// [`respond`]: #method.respond
 #[derive(Debug)]
-#[doc(hidden)]
-pub struct AnswerSender(oneshot::Sender<SignedMessage>);
+pub struct AnswerSender(oneshot::Sender<SignedMessage>, RefAddr);
 
 #[derive(Debug)]
 /// A [`Future`] returned when successfully "asking" a
-/// message using [`ChildRef::ask`] and which resolves to
+/// message using [`ChildRef::ask_anonymously`] and which resolves to
 /// a `Result<Msg, ()>` where the [`Msg`] is the message
 /// answered by the child (see the [`msg!`] macro for more
 /// information).
@@ -49,7 +66,18 @@ pub struct AnswerSender(oneshot::Sender<SignedMessage>);
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 ///     # Bastion::init();
 /// // The message that will be "asked"...
 /// const ASK_MSG: &'static str = "A message containing data (ask).";
@@ -109,10 +137,8 @@ pub struct AnswerSender(oneshot::Sender<SignedMessage>);
 /// # }
 /// ```
 ///
-/// [`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
-/// [`ChildRef::ask`]: ../children/struct.ChildRef.html#method.ask
-/// [`Msg`]: message/struct.Msg.html
-/// [`msg!`]: macro.msg.html
+/// [`Future`]: std::future::Future
+/// [`ChildRef::ask_anonymously`]: crate::child_ref::ChildRef::ask_anonymously
 pub struct Answer(Receiver<SignedMessage>);
 
 #[derive(Debug)]
@@ -125,7 +151,18 @@ pub struct Answer(Receiver<SignedMessage>);
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 ///     # Bastion::init();
 /// Bastion::children(|children| {
 ///     children.with_exec(|ctx: BastionContext| {
@@ -171,9 +208,8 @@ pub struct Answer(Receiver<SignedMessage>);
 /// # }
 /// ```
 ///
-/// [`BastionContext::recv`]: context/struct.BastionContext.html#method.recv
-/// [`BastionContext::try_recv`]: context/struct.BastionContext.html#method.try_recv
-/// [`msg!`]: macro.msg.html
+/// [`BastionContext::recv`]: crate::context::BastionContext::recv
+/// [`BastionContext::try_recv`]: crate::context::BastionContext::try_recv
 pub struct Msg(MsgInner);
 
 #[derive(Debug)]
@@ -200,7 +236,7 @@ pub(crate) enum BastionMessage {
     InstantiatedChild {
         parent_id: BastionId,
         child_id: BastionId,
-        state: Arc<Mutex<Pin<Box<ContextState>>>>,
+        state: Arc<Pin<Box<ContextState>>>,
     },
     Message(Msg),
     RestartRequired {
@@ -214,13 +250,13 @@ pub(crate) enum BastionMessage {
     RestartSubtree,
     RestoreChild {
         id: BastionId,
-        state: Arc<Mutex<Pin<Box<ContextState>>>>,
+        state: Arc<Pin<Box<ContextState>>>,
     },
     DropChild {
         id: BastionId,
     },
     SetState {
-        state: Arc<Mutex<Pin<Box<ContextState>>>>,
+        state: Arc<Pin<Box<ContextState>>>,
     },
     Stopped {
         id: BastionId,
@@ -238,14 +274,17 @@ pub(crate) enum Deployment {
 }
 
 impl AnswerSender {
-    // FIXME: we can't let manipulating Signature in a public API
-    // but now it's being called only by a macro so we are trusting it
-    #[doc(hidden)]
-    pub fn send<M: Message>(self, msg: M, sign: RefAddr) -> Result<(), M> {
+    /// Sends data back to the original sender.
+    ///
+    /// Returns  `Ok` if the data was sent successfully, otherwise returns the
+    /// original data.
+    pub fn reply<M: Message>(self, msg: M) -> Result<(), M> {
         debug!("{:?}: Sending answer: {:?}", self, msg);
         let msg = Msg::tell(msg);
         trace!("{:?}: Sending message: {:?}", self, msg);
-        self.0
+
+        let AnswerSender(sender, sign) = self;
+        sender
             .send(SignedMessage::new(msg, sign))
             .map_err(|smsg| smsg.msg.try_unwrap().unwrap())
     }
@@ -262,10 +301,10 @@ impl Msg {
         Msg(inner)
     }
 
-    pub(crate) fn ask<M: Message>(msg: M) -> (Self, Answer) {
+    pub(crate) fn ask<M: Message>(msg: M, sign: RefAddr) -> (Self, Answer) {
         let msg = Box::new(msg);
         let (sender, recver) = oneshot::channel();
-        let sender = AnswerSender(sender);
+        let sender = AnswerSender(sender, sign);
         let answer = Answer(recver);
 
         let sender = Some(sender);
@@ -378,6 +417,16 @@ impl Msg {
     }
 }
 
+impl AsRef<dyn Any> for Msg {
+    fn as_ref(&self) -> &dyn Any {
+        match &self.0 {
+            MsgInner::Broadcast(msg) => msg.as_ref(),
+            MsgInner::Tell(msg) => msg.as_ref(),
+            MsgInner::Ask { msg, .. } => msg.as_ref(),
+        }
+    }
+}
+
 impl BastionMessage {
     pub(crate) fn start() -> Self {
         BastionMessage::Start
@@ -418,7 +467,7 @@ impl BastionMessage {
     pub(crate) fn instantiated_child(
         parent_id: BastionId,
         child_id: BastionId,
-        state: Arc<Mutex<Pin<Box<ContextState>>>>,
+        state: Arc<Pin<Box<ContextState>>>,
     ) -> Self {
         BastionMessage::InstantiatedChild {
             parent_id,
@@ -437,8 +486,8 @@ impl BastionMessage {
         BastionMessage::Message(msg)
     }
 
-    pub(crate) fn ask<M: Message>(msg: M) -> (Self, Answer) {
-        let (msg, answer) = Msg::ask(msg);
+    pub(crate) fn ask<M: Message>(msg: M, sign: RefAddr) -> (Self, Answer) {
+        let (msg, answer) = Msg::ask(msg, sign);
         (BastionMessage::Message(msg), answer)
     }
 
@@ -454,7 +503,7 @@ impl BastionMessage {
         BastionMessage::RestartSubtree
     }
 
-    pub(crate) fn restore_child(id: BastionId, state: Arc<Mutex<Pin<Box<ContextState>>>>) -> Self {
+    pub(crate) fn restore_child(id: BastionId, state: Arc<Pin<Box<ContextState>>>) -> Self {
         BastionMessage::RestoreChild { id, state }
     }
 
@@ -462,7 +511,7 @@ impl BastionMessage {
         BastionMessage::DropChild { id }
     }
 
-    pub(crate) fn set_state(state: Arc<Mutex<Pin<Box<ContextState>>>>) -> Self {
+    pub(crate) fn set_state(state: Arc<Pin<Box<ContextState>>>) -> Self {
         BastionMessage::SetState { state }
     }
 
@@ -572,7 +621,18 @@ impl Future for Answer {
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 ///     # Bastion::init();
 /// // The message that will be broadcasted...
 /// const BCAST_MSG: &'static str = "A message containing data (broadcast).";
@@ -625,9 +685,8 @@ impl Future for Answer {
 /// # }
 /// ```
 ///
-/// [`Msg`]: children/struct.Msg.html
-/// [`BastionContext::recv`]: context/struct.BastionContext.html#method.recv
-/// [`BastionContext::try_recv`]: context/struct.BastionContext.html#method.try_recv
+/// [`BastionContext::recv`]: crate::context::BastionContext::recv
+/// [`BastionContext::try_recv`]: crate::context::BastionContext::try_recv
 macro_rules! msg {
     ($msg:expr, $($tokens:tt)+) => {
         msg!(@internal $msg, (), (), (), $($tokens)+)
@@ -734,7 +793,7 @@ macro_rules! msg {
                 ($ctx:expr, $answer:expr) => {
                     {
                         let sign = $ctx.signature();
-                        sender.send($answer, sign)
+                        sender.reply($answer)
                     }
                 };
             }
@@ -776,7 +835,18 @@ macro_rules! msg {
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 ///     # Bastion::init();
 ///     # let children_ref =
 /// // Create a new child...
@@ -818,6 +888,263 @@ macro_rules! answer {
     ($msg:expr, $answer:expr) => {{
         let (mut msg, sign) = $msg.extract();
         let sender = msg.take_sender().expect("failed to take render");
-        sender.send($answer, sign)
+        sender.reply($answer)
     }};
 }
+
+#[derive(Debug)]
+enum MessageHandlerState<O> {
+    Matched(O),
+    Unmatched(SignedMessage),
+}
+
+impl<O> MessageHandlerState<O> {
+    fn take_message(self) -> Result<SignedMessage, O> {
+        match self {
+            MessageHandlerState::Unmatched(msg) => Ok(msg),
+            MessageHandlerState::Matched(output) => Err(output),
+        }
+    }
+
+    fn output_or_else(self, f: impl FnOnce(SignedMessage) -> O) -> O {
+        match self {
+            MessageHandlerState::Matched(output) => output,
+            MessageHandlerState::Unmatched(msg) => f(msg),
+        }
+    }
+}
+
+/// Matches a [`Msg`] (as returned by [`BastionContext::recv`]
+/// or [`BastionContext::try_recv`]) with different types.
+///
+/// This type may replace the [`msg!`] macro in the future.
+///
+/// The [`new`] function creates a new [`MessageHandler`], which is then
+/// matched on with the `on_*` functions.
+///
+/// There are different kind of messages:
+///   - messages that are broadcasted, which can be matched with the
+///     [`on_broadcast`] method,
+///   - messages that can be responded to, which are matched with the
+///     [`on_question`] method,
+///   - messages that can not be responded to, which are matched with
+///     [`on_tell`],
+///   - fallback case, which matches everything, entitled [`on_fallback`].
+///
+/// The closure passed to the functions described previously must return the
+/// same type. This value is retrieved when [`on_fallback`] is invoked.
+///
+/// Questions can be responded to by calling [`reply`] on the provided
+/// sender.
+///
+/// # Example
+///
+/// ```rust
+/// # use bastion::prelude::*;
+/// # use bastion::message::MessageHandler;
+/// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
+///     # Bastion::init();
+/// // The message that will be broadcasted...
+/// const BCAST_MSG: &'static str = "A message containing data (broadcast).";
+/// // The message that will be "told" to the child...
+/// const TELL_MSG: &'static str = "A message containing data (tell).";
+/// // The message that will be "asked" to the child...
+/// const ASK_MSG: &'static str = "A message containing data (ask).";
+///
+/// Bastion::children(|children| {
+///     children.with_exec(|ctx: BastionContext| {
+///         async move {
+///             # ctx.tell(&ctx.current().addr(), TELL_MSG).unwrap();
+///             # ctx.ask(&ctx.current().addr(), ASK_MSG).unwrap();
+///             #
+///             loop {
+///                 MessageHandler::new(ctx.recv().await?)
+///                     // We match on broadcasts of &str
+///                     .on_broadcast(|msg: &&str, _sender_addr| {
+///                         assert_eq!(*msg, BCAST_MSG);
+///                         // Handle the message...
+///                     })
+///                     // We match on messages of &str
+///                     .on_tell(|msg: &str, _sender_addr| {
+///                         assert_eq!(msg, TELL_MSG);
+///                         // Handle the message...
+///                     })
+///                     // We match on questions of &str
+///                     .on_question(|msg: &str, sender| {
+///                         assert_eq!(msg, ASK_MSG);
+///                         // Handle the message...
+///
+///                         // ...and eventually answer to it...
+///                         sender.reply("An answer to the message.");
+///                     })
+///                     // We are only broadcasting, "telling" and "asking" a
+///                     // `&str` in this example, so we know that this won't
+///                     // happen...
+///                     .on_fallback(|msg, _sender_addr| ());
+///             }
+///         }
+///     })
+/// }).expect("Couldn't start the children group.");
+///     #
+///     # Bastion::start();
+///     # Bastion::broadcast(BCAST_MSG).unwrap();
+///     # Bastion::stop();
+///     # Bastion::block_until_stopped();
+/// # }
+/// ```
+///
+/// [`BastionContext::recv`]: crate::context::BastionContext::recv
+/// [`BastionContext::try_recv`]: crate::context::BastionContext::try_recv
+/// [`new`]: Self::new
+/// [`on_broadcast`]: Self::on_broadcast
+/// [`on_question`]: Self::on_question
+/// [`on_tell`]: Self::on_tell
+/// [`on_fallback`]: Self::on_fallback
+/// [`reply`]: AnswerSender::reply
+#[derive(Debug)]
+pub struct MessageHandler<O> {
+    state: MessageHandlerState<O>,
+}
+
+impl<O> MessageHandler<O> {
+    /// Creates a new [`MessageHandler`] with an incoming message.
+    pub fn new(msg: SignedMessage) -> MessageHandler<O> {
+        let state = MessageHandlerState::Unmatched(msg);
+        MessageHandler { state }
+    }
+
+    /// Matches on a question of a specific type.
+    ///
+    /// This will consume the inner data and call `f` if the contained message
+    /// can be replied to.
+    pub fn on_question<T, F>(self, f: F) -> MessageHandler<O>
+    where
+        T: 'static,
+        F: FnOnce(T, AnswerSender) -> O,
+    {
+        match self.try_into_question::<T>() {
+            Ok((arg, sender)) => {
+                let val = f(arg, sender);
+                MessageHandler::matched(val)
+            }
+            Err(this) => this,
+        }
+    }
+
+    /// Calls a fallback function if the message has still not matched yet.
+    ///
+    /// This consumes the [`MessageHandler`], so that no matching can be
+    /// performed anymore.
+    pub fn on_fallback<F>(self, f: F) -> O
+    where
+        F: FnOnce(&dyn Any, RefAddr) -> O,
+    {
+        self.state
+            .output_or_else(|SignedMessage { msg, sign }| f(msg.as_ref(), sign))
+    }
+
+    /// Calls a function if the incoming message is a broadcast and has a
+    /// specific type.
+    pub fn on_broadcast<T, F>(self, f: F) -> MessageHandler<O>
+    where
+        T: 'static + Send + Sync,
+        F: FnOnce(&T, RefAddr) -> O,
+    {
+        match self.try_into_broadcast::<T>() {
+            Ok((arg, addr)) => {
+                let val = f(arg.as_ref(), addr);
+                MessageHandler::matched(val)
+            }
+            Err(this) => this,
+        }
+    }
+
+    /// Calls a function if the incoming message can't be replied to and has a
+    /// specific type.
+    pub fn on_tell<T, F>(self, f: F) -> MessageHandler<O>
+    where
+        T: Debug + 'static,
+        F: FnOnce(T, RefAddr) -> O,
+    {
+        match self.try_into_tell::<T>() {
+            Ok((msg, addr)) => {
+                let val = f(msg, addr);
+                MessageHandler::matched(val)
+            }
+            Err(this) => this,
+        }
+    }
+
+    fn matched(output: O) -> MessageHandler<O> {
+        let state = MessageHandlerState::Matched(output);
+        MessageHandler { state }
+    }
+
+    fn try_into_question<T: 'static>(self) -> Result<(T, AnswerSender), MessageHandler<O>> {
+        debug!("try_into_question with type {}", std::any::type_name::<T>());
+        match self.state.take_message() {
+            Ok(SignedMessage {
+                msg:
+                    Msg(MsgInner::Ask {
+                        msg,
+                        sender: Some(sender),
+                    }),
+                ..
+            }) if msg.is::<T>() => {
+                let msg: Box<dyn Any> = msg;
+                Ok((*msg.downcast::<T>().unwrap(), sender))
+            }
+
+            Ok(anything) => Err(MessageHandler::new(anything)),
+            Err(output) => Err(MessageHandler::matched(output)),
+        }
+    }
+
+    fn try_into_broadcast<T: Send + Sync + 'static>(
+        self,
+    ) -> Result<(Arc<T>, RefAddr), MessageHandler<O>> {
+        debug!(
+            "try_into_broadcast with type {}",
+            std::any::type_name::<T>()
+        );
+        match self.state.take_message() {
+            Ok(SignedMessage {
+                msg: Msg(MsgInner::Broadcast(msg)),
+                sign,
+            }) if msg.is::<T>() => {
+                let msg: Arc<dyn Any + Send + Sync + 'static> = msg;
+                Ok((msg.downcast::<T>().unwrap(), sign))
+            }
+
+            Ok(anything) => Err(MessageHandler::new(anything)),
+            Err(output) => Err(MessageHandler::matched(output)),
+        }
+    }
+
+    fn try_into_tell<T: Debug + 'static>(self) -> Result<(T, RefAddr), MessageHandler<O>> {
+        debug!("try_into_tell with type {}", std::any::type_name::<T>());
+        match self.state.take_message() {
+            Ok(SignedMessage {
+                msg: Msg(MsgInner::Tell(msg)),
+                sign,
+            }) if msg.is::<T>() => {
+                let msg: Box<dyn Any> = msg;
+                Ok((*msg.downcast::<T>().unwrap(), sign))
+            }
+            Ok(anything) => Err(MessageHandler::new(anything)),
+            Err(output) => Err(MessageHandler::matched(output)),
+        }
+    }
+}
diff --git a/src/bastion/src/path.rs b/src/bastion/src/path.rs
index ab4fec16..ee856ae0 100644
--- a/src/bastion/src/path.rs
+++ b/src/bastion/src/path.rs
@@ -17,7 +17,18 @@ use std::result::Result;
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
 /// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 ///     # Bastion::init();
 ///
 ///     # Bastion::children(|children| {
@@ -72,7 +83,18 @@ impl BastionPath {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     ///     # let children_ref = Bastion::children(|children| children).unwrap();
@@ -113,7 +135,18 @@ impl BastionPath {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     ///     # let children_ref = Bastion::children(|children| children).unwrap();
@@ -154,7 +187,18 @@ impl BastionPath {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     ///     # let children_ref = Bastion::children(|children| children).unwrap();
@@ -205,19 +249,8 @@ impl fmt::Display for BastionPath {
 impl fmt::Debug for BastionPath {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match &self.this {
-            Some(this @ BastionPathElement::Supervisor(_)) => write!(
-                f,
-                "/{}",
-                self.parent_chain
-                    .iter()
-                    .map(|id| BastionPathElement::Supervisor(id.clone()))
-                    .chain(vec![this.clone()])
-                    .map(|el| format!("{:?}", el))
-                    .collect::<Vec<String>>()
-                    .join("/")
-            ),
-            // TODO: combine with the pattern above when or-patterns become stable
-            Some(this @ BastionPathElement::Children(_)) => write!(
+            Some(this @ BastionPathElement::Supervisor(_))
+            | Some(this @ BastionPathElement::Children(_)) => write!(
                 f,
                 "/{}",
                 self.parent_chain
@@ -263,6 +296,18 @@ impl fmt::Debug for BastionPath {
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 ///
@@ -284,6 +329,7 @@ impl fmt::Debug for BastionPath {
 /// #
 /// # Bastion::start();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 pub enum BastionPathElement {
     #[doc(hidden)]
@@ -333,6 +379,18 @@ impl BastionPathElement {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     ///
     /// Bastion::children(|children| {
@@ -353,6 +411,7 @@ impl BastionPathElement {
     /// #
     /// # Bastion::start();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn is_child(&self) -> bool {
         matches!(self, BastionPathElement::Child(_))
diff --git a/src/bastion/src/resizer.rs b/src/bastion/src/resizer.rs
index a6a20266..e46c5744 100644
--- a/src/bastion/src/resizer.rs
+++ b/src/bastion/src/resizer.rs
@@ -112,9 +112,23 @@ impl OptimalSizeExploringResizer {
         self.actor_stats.clone()
     }
 
+    /// Returns lower bound of the number of actors in the scaling group.
+    pub(crate) fn lower_bound(&self) -> u64 {
+        self.lower_bound
+    }
+
+    /// Set lower bound of the autoscaling group.
+    pub(crate) fn set_lower_bound(&mut self, lower_bound: u64) {
+        self.lower_bound = lower_bound;
+    }
+
     /// Overrides the minimal amount of actors available to use.
     pub fn with_lower_bound(mut self, lower_bound: u64) -> Self {
-        self.lower_bound = lower_bound;
+        if lower_bound == u64::MIN {
+            self.lower_bound = lower_bound.saturating_add(1);
+        } else {
+            self.lower_bound = lower_bound;
+        }
         self
     }
 
diff --git a/src/bastion/src/routing/mod.rs b/src/bastion/src/routing/mod.rs
new file mode 100644
index 00000000..f8a360ae
--- /dev/null
+++ b/src/bastion/src/routing/mod.rs
@@ -0,0 +1,5 @@
+pub mod path;
+pub mod target;
+
+pub use crate::routing::path::{ActorPath, NodeType, Scope};
+pub use crate::routing::target::Target;
diff --git a/src/bastion/src/routing/path.rs b/src/bastion/src/routing/path.rs
new file mode 100644
index 00000000..460857d5
--- /dev/null
+++ b/src/bastion/src/routing/path.rs
@@ -0,0 +1,399 @@
+//!
+//! Module with structs for handling paths on the cluster, a system
+//! or a local group level.
+//!
+use std::net::SocketAddr;
+use std::string::ToString;
+use uuid::Uuid;
+
+/// Special wrapper for handling actor's path and
+/// message distribution.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct ActorPath {
+    /// Node name in the cluster.
+    node_name: String,
+    /// Defines actors in the local or the remote node.
+    node_type: NodeType,
+    /// Defines actors in the top-level namespace.
+    scope: Scope,
+    /// A unique name of the actor or namespace
+    name: String,
+}
+
+/// A part of path that defines remote or local machine
+/// with running supervisors and actors.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum NodeType {
+    /// The message must be delivered in terms of
+    /// the local node.
+    Local,
+    /// The message must be delivered to the remote
+    /// node in the cluster by the certain host and port.
+    Remote(SocketAddr),
+}
+
+/// A part of path that defines to what part of the node
+/// the message must be delivered.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum Scope {
+    /// Broadcast the message to user-defined actors, defined
+    /// before starting an application.
+    User,
+    /// Broadcast the message to top-level built-in actors. For
+    /// example it can be logging, configuration, heartbeat actors.
+    System,
+    /// The message wasn't delivered because the node was
+    /// stopped or not available.
+    DeadLetter,
+    /// The message must be delivered to short-living actors or subtrees of
+    /// actors spawned in runtime.
+    Temporary,
+}
+
+impl ActorPath {
+    /// Returns a ActorPath instance, constructed from parts.
+    pub(crate) fn new(node_name: &str, node_type: NodeType, scope: Scope, name: &str) -> Self {
+        ActorPath {
+            node_name: node_name.to_string(),
+            node_type,
+            scope,
+            name: name.to_string(),
+        }
+    }
+
+    /// Replaces the existing node name onto the new one.
+    pub fn node_name(mut self, node_name: &str) -> Self {
+        self.node_name = node_name.to_string();
+        self
+    }
+
+    /// Replaces the existing node type onto the new one.
+    pub fn node_type(mut self, node_type: NodeType) -> Self {
+        self.node_type = node_type;
+        self
+    }
+
+    /// Replaces the existing scope onto the new one.
+    pub fn scope(mut self, scope: Scope) -> Self {
+        self.scope = scope;
+        self
+    }
+
+    /// Replaces the existing actor name onto the new one.
+    pub fn name(mut self, name: &str) -> Self {
+        self.name = name.trim_start_matches("/").to_string();
+        self
+    }
+
+    /// Method for checking that the path is related to the local node
+    pub fn is_local(&self) -> bool {
+        self.node_type == NodeType::Local
+    }
+
+    /// Method for checking that the path is related to the remote node
+    pub fn is_remote(&self) -> bool {
+        match self.node_type {
+            NodeType::Remote(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Method for checking that path is addressing to user-defined actors
+    pub fn is_user_scope(&self) -> bool {
+        self.scope == Scope::User
+    }
+
+    /// Method for checking that path is addressing to system actors
+    pub fn is_system_scope(&self) -> bool {
+        self.scope == Scope::System
+    }
+
+    /// Method for checking that path is addressing to dead letter scope
+    pub fn is_dead_letter_scope(&self) -> bool {
+        self.scope == Scope::DeadLetter
+    }
+
+    /// Method for checking that path is addressing to temporary actors
+    pub fn is_temporary_scope(&self) -> bool {
+        self.scope == Scope::Temporary
+    }
+}
+
+impl Default for ActorPath {
+    fn default() -> Self {
+        let unique_id = Uuid::new_v4().to_string();
+        ActorPath::new("node", NodeType::Local, Scope::User, &unique_id)
+    }
+}
+
+impl ToString for ActorPath {
+    fn to_string(&self) -> String {
+        let node_type = self.node_type.to_string();
+        let scope = self.scope.as_str();
+        format!(
+            "bastion://{}{}/{}/{}",
+            self.node_name, node_type, scope, self.name
+        )
+    }
+}
+
+impl ToString for NodeType {
+    fn to_string(&self) -> String {
+        match self {
+            NodeType::Local => String::new(),
+            NodeType::Remote(address) => format!("@{}", address.to_string()),
+        }
+    }
+}
+
+impl Scope {
+    fn as_str(&self) -> &str {
+        match self {
+            Scope::User => "user",
+            Scope::System => "system",
+            Scope::DeadLetter => "dead_letter",
+            Scope::Temporary => "temporary",
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::routing::path::{ActorPath, NodeType, Scope};
+    use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+
+    #[test]
+    fn construct_local_user_path_group() {
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Local)
+            .scope(Scope::User)
+            .name("processing/1");
+
+        assert_eq!(instance.to_string(), "bastion://test/user/processing/1");
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_user_scope(), true);
+    }
+
+    #[test]
+    fn construct_local_system_path_group() {
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Local)
+            .scope(Scope::System)
+            .name("processing/1");
+
+        assert_eq!(instance.to_string(), "bastion://test/system/processing/1");
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_system_scope(), true);
+    }
+
+    #[test]
+    fn construct_local_dead_letter_path_group() {
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Local)
+            .scope(Scope::DeadLetter)
+            .name("processing/1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://test/dead_letter/processing/1"
+        );
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_dead_letter_scope(), true);
+    }
+
+    #[test]
+    fn construct_local_temporary_path_group() {
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Local)
+            .scope(Scope::Temporary)
+            .name("processing/1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://test/temporary/processing/1"
+        );
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_temporary_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_user_path_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::User)
+            .name("processing/1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://test@127.0.0.1:8080/user/processing/1"
+        );
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_user_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_system_path_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::System)
+            .name("processing/1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://test@127.0.0.1:8080/system/processing/1"
+        );
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_system_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_dead_letter_path_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::DeadLetter)
+            .name("processing/1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://test@127.0.0.1:8080/dead_letter/processing/1"
+        );
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_dead_letter_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_temporary_path_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_name("test")
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::Temporary)
+            .name("processing/1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://test@127.0.0.1:8080/temporary/processing/1"
+        );
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_temporary_scope(), true);
+    }
+
+    #[test]
+    fn construct_local_user_path_without_group() {
+        let instance = ActorPath::default()
+            .node_type(NodeType::Local)
+            .scope(Scope::User)
+            .name("1");
+
+        assert_eq!(instance.to_string(), "bastion://node/user/1");
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_user_scope(), true);
+    }
+
+    #[test]
+    fn construct_local_system_path_without_group() {
+        let instance = ActorPath::default()
+            .node_type(NodeType::Local)
+            .scope(Scope::System)
+            .name("1");
+
+        assert_eq!(instance.to_string(), "bastion://node/system/1");
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_system_scope(), true);
+    }
+
+    #[test]
+    fn construct_local_dead_letter_path_without_group() {
+        let instance = ActorPath::default()
+            .node_type(NodeType::Local)
+            .scope(Scope::DeadLetter)
+            .name("1");
+
+        assert_eq!(instance.to_string(), "bastion://node/dead_letter/1");
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_dead_letter_scope(), true);
+    }
+
+    #[test]
+    fn construct_local_temporary_path_without_group() {
+        let instance = ActorPath::default()
+            .node_type(NodeType::Local)
+            .scope(Scope::Temporary)
+            .name("1");
+
+        assert_eq!(instance.to_string(), "bastion://node/temporary/1");
+        assert_eq!(instance.is_local(), true);
+        assert_eq!(instance.is_temporary_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_user_path_without_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::User)
+            .name("1");
+
+        assert_eq!(instance.to_string(), "bastion://node@127.0.0.1:8080/user/1");
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_user_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_system_path_without_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::System)
+            .name("1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://node@127.0.0.1:8080/system/1"
+        );
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_system_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_dead_letter_path_without_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::DeadLetter)
+            .name("1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://node@127.0.0.1:8080/dead_letter/1"
+        );
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_dead_letter_scope(), true);
+    }
+
+    #[test]
+    fn construct_remote_temporary_path_without_group() {
+        let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+        let instance = ActorPath::default()
+            .node_type(NodeType::Remote(address))
+            .scope(Scope::Temporary)
+            .name("1");
+
+        assert_eq!(
+            instance.to_string(),
+            "bastion://node@127.0.0.1:8080/temporary/1"
+        );
+        assert_eq!(instance.is_remote(), true);
+        assert_eq!(instance.is_temporary_scope(), true);
+    }
+}
diff --git a/src/bastion/src/routing/target.rs b/src/bastion/src/routing/target.rs
new file mode 100644
index 00000000..b7b082b1
--- /dev/null
+++ b/src/bastion/src/routing/target.rs
@@ -0,0 +1,261 @@
+use crate::routing::ActorPath;
+use lazy_static::lazy_static;
+use regex::Regex;
+
+lazy_static! {
+    static ref WILDCARD_REGEX: Regex = Regex::new(r"(\*/)").unwrap();
+}
+
+/// An enum for handling targeting messages to the certain
+/// actor, a group of actors, a namespace or a scope.
+#[derive(Debug, Clone)]
+pub enum Target<'a> {
+    /// The message must be delivered to the actor(s) by
+    /// the matched path.
+    Path(ActorPath),
+    /// The message must be delivered to actor(s), organized
+    /// under the named group.
+    Group(&'a str),
+}
+
+/// A wrapper for the Target enum type that provides an additional
+/// functionality in matching actor paths with the desired pattern.
+pub(crate) struct EnvelopeTarget<'a> {
+    target: Target<'a>,
+    regex: Option<Regex>,
+}
+
+impl<'a> EnvelopeTarget<'a> {
+    /// Compares the given path with the declared path
+    pub(crate) fn is_match(&self, actor_path: &ActorPath) -> bool {
+        match &self.target {
+            // Just do a regular matching by path, or via the regular
+            // expression if the path contains wildcard symbols.
+            Target::Path(path) => match &self.regex {
+                Some(regex) => {
+                    let stringified_path = actor_path.to_string();
+                    regex.is_match(&stringified_path)
+                }
+                None => actor_path == path,
+            },
+            // False, because the group name is not a part of the actor's path.
+            Target::Group(_) => false,
+        }
+    }
+
+    /// Returns a group name, extracted from the target field.
+    pub(crate) fn get_group_name(&self) -> Option<&'a str> {
+        match self.target {
+            Target::Group(group_name) => Some(group_name),
+            _ => None,
+        }
+    }
+}
+
+impl<'a> From<Target<'a>> for EnvelopeTarget<'a> {
+    fn from(target: Target<'a>) -> Self {
+        let regex = match &target {
+            // For a path regex is optional. But it needs to be generated, if
+            // the user specified wildcards, such as asterisks symbols.
+            Target::Path(path) => {
+                let stringified_path = path.to_string();
+
+                match stringified_path.contains("/*") {
+                    // Exists at least one wildcard that needs to be replaced
+                    // onto the regular expression.
+                    true => {
+                        let raw_regex = match stringified_path.ends_with("/*") {
+                            // Necessary to replace the ending, so that any path with
+                            // any nested level can be considered as a correct one.
+                            true => {
+                                let mut fixed_path = stringified_path;
+                                let index = fixed_path.rfind("/*").unwrap();
+                                fixed_path.replace_range(index.., r"/[[\w\d\-_]/?]+");
+                                fixed_path
+                            }
+                            // Common case: the wildcard closed by the "/" character
+                            false => stringified_path,
+                        };
+
+                        let raw_regex = format!(
+                            "{}$",
+                            WILDCARD_REGEX.replace_all(&raw_regex, r"[\w\d\-_.]+/")
+                        );
+                        let compiled_regex = Regex::new(&raw_regex).unwrap();
+                        Some(compiled_regex)
+                    }
+                    // Wildcard wasn't specified in the path: no needed to
+                    // generate a regular expression here.
+                    false => None,
+                }
+            }
+            // For a group regex doesn't required. Always do
+            // a direct string comparison in dispatchers.
+            Target::Group(_) => None,
+        };
+
+        EnvelopeTarget { target, regex }
+    }
+}
+
+#[cfg(test)]
+mod message_target_tests {
+    use crate::routing::path::ActorPath;
+    use crate::routing::target::{EnvelopeTarget, Target};
+
+    #[test]
+    fn test_get_group_name_returns_str_reference() {
+        let target = Target::Group("test");
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let result = envelope_target.get_group_name();
+        assert_eq!(result.is_some(), true);
+        assert_eq!(result.unwrap(), "test");
+    }
+
+    #[test]
+    fn test_get_group_name_returns_none_for_target_path_type() {
+        let path = ActorPath::default().name("test");
+        let target = Target::Path(path.clone());
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let result = envelope_target.get_group_name();
+        assert_eq!(result.is_none(), true);
+    }
+
+    #[test]
+    fn test_match_by_path_with_without_a_wildcard_returns_true() {
+        let path = ActorPath::default().name("test");
+        let target = Target::Path(path.clone());
+        let envelope_target = EnvelopeTarget::from(target);
+
+        assert_eq!(envelope_target.is_match(&path), true);
+    }
+
+    #[test]
+    fn test_match_by_path_with_without_a_wildcard_returns_false() {
+        let path = ActorPath::default().name("test");
+        let target = Target::Path(path);
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let validated_path = ActorPath::default().name("not_matched");
+        assert_eq!(envelope_target.is_match(&validated_path), false);
+    }
+
+    #[test]
+    fn test_match_by_path_with_a_single_wildcard_in_the_beginning() {
+        let path = ActorPath::default().name("*/processing/a");
+        let target = Target::Path(path);
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let valid_path_1 = ActorPath::default().name("first/processing/a");
+        let valid_path_2 = ActorPath::default().name("second/processing/a");
+        let invalid_path = ActorPath::default().name("third/handling/a");
+        assert_eq!(envelope_target.is_match(&valid_path_1), true);
+        assert_eq!(envelope_target.is_match(&valid_path_2), true);
+        assert_eq!(envelope_target.is_match(&invalid_path), false);
+    }
+
+    #[test]
+    fn test_match_by_path_with_a_single_wildcard_in_the_middle() {
+        let path = ActorPath::default().name("first/*/a");
+        let target = Target::Path(path);
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let valid_path = ActorPath::default().name("first/processing/a");
+        let invalid_path_1 = ActorPath::default().name("first/processing/b");
+        let invalid_path_2 = ActorPath::default().name("first/processing/nested/a");
+        let invalid_path_3 = ActorPath::default().name("second/handling/nested/a");
+        assert_eq!(envelope_target.is_match(&valid_path), true);
+        assert_eq!(envelope_target.is_match(&invalid_path_1), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_2), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_3), false);
+    }
+
+    #[test]
+    fn test_match_by_path_with_a_single_wildcard_in_the_end() {
+        let path = ActorPath::default().name("first/*");
+        let target = Target::Path(path);
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let valid_path_1 = ActorPath::default().name("first/a");
+        let valid_path_2 = ActorPath::default().name("first/processing/a");
+        let valid_path_3 = ActorPath::default().name("first/processing/b");
+        let valid_path_4 = ActorPath::default().name("first/processing/nested/a");
+        let invalid_path_1 = ActorPath::default().name("second/a");
+        let invalid_path_2 = ActorPath::default().name("second/nested/a");
+        assert_eq!(envelope_target.is_match(&valid_path_1), true);
+        assert_eq!(envelope_target.is_match(&valid_path_2), true);
+        assert_eq!(envelope_target.is_match(&valid_path_3), true);
+        assert_eq!(envelope_target.is_match(&valid_path_4), true);
+        assert_eq!(envelope_target.is_match(&invalid_path_1), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_2), false);
+    }
+
+    #[test]
+    fn test_match_by_path_with_a_single_and_limited_nesting_wildcard() {
+        let path = ActorPath::default().name("first/*/");
+        let target = Target::Path(path);
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let valid_path_1 = ActorPath::default().name("first/a/");
+        let valid_path_2 = ActorPath::default().name("first/b/");
+        let invalid_path_1 = ActorPath::default().name("first/handling/a");
+        let invalid_path_2 = ActorPath::default().name("first/processing/b");
+        let invalid_path_3 = ActorPath::default().name("first/processing/nested/a");
+        let invalid_path_4 = ActorPath::default().name("second/a");
+        let invalid_path_5 = ActorPath::default().name("second/nested/b");
+        assert_eq!(envelope_target.is_match(&valid_path_1), true);
+        assert_eq!(envelope_target.is_match(&valid_path_2), true);
+        assert_eq!(envelope_target.is_match(&invalid_path_1), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_2), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_3), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_4), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_5), false);
+    }
+
+    #[test]
+    fn test_match_by_path_with_multiple_wildcards() {
+        let path = ActorPath::default().name("*/*/a");
+        let target = Target::Path(path);
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let valid_path_1 = ActorPath::default().name("first/handling/a");
+        let valid_path_2 = ActorPath::default().name("first/processing/a");
+        let invalid_path_1 = ActorPath::default().name("first/processing/nested/a");
+        let invalid_path_2 = ActorPath::default().name("second/a");
+        let invalid_path_3 = ActorPath::default().name("second/nested/b");
+        assert_eq!(envelope_target.is_match(&valid_path_1), true);
+        assert_eq!(envelope_target.is_match(&valid_path_2), true);
+        assert_eq!(envelope_target.is_match(&invalid_path_1), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_2), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_3), false);
+    }
+
+    #[test]
+    fn test_match_by_path_with_a_single_wildcard_against_a_path_with_special_symbols() {
+        let path = ActorPath::default().name("first/*/a");
+        let target = Target::Path(path);
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let valid_path_1 = ActorPath::default().name("first/hand.ling/a");
+        let valid_path_2 = ActorPath::default().name("first/proce-ssing/a");
+        let valid_path_3 = ActorPath::default().name("first/some_thing/a");
+        let invalid_path_2 = ActorPath::default().name("second/a");
+        let invalid_path_3 = ActorPath::default().name("second/nested/b");
+        assert_eq!(envelope_target.is_match(&valid_path_1), true);
+        assert_eq!(envelope_target.is_match(&valid_path_2), true);
+        assert_eq!(envelope_target.is_match(&valid_path_3), true);
+        assert_eq!(envelope_target.is_match(&invalid_path_2), false);
+        assert_eq!(envelope_target.is_match(&invalid_path_3), false);
+    }
+
+    #[test]
+    fn test_match_by_group_returns_false() {
+        let target = Target::Group("test");
+        let envelope_target = EnvelopeTarget::from(target);
+
+        let actor_path = ActorPath::default();
+        assert_eq!(envelope_target.is_match(&actor_path), false);
+    }
+}
diff --git a/src/bastion/src/supervisor.rs b/src/bastion/src/supervisor.rs
index d12a086d..273ea9e2 100644
--- a/src/bastion/src/supervisor.rs
+++ b/src/bastion/src/supervisor.rs
@@ -9,7 +9,7 @@ use crate::context::{BastionId, ContextState};
 use crate::envelope::Envelope;
 use crate::message::{BastionMessage, Deployment, Message};
 use crate::path::{BastionPath, BastionPathElement};
-use async_mutex::Mutex;
+
 use bastion_executor::pool;
 use futures::prelude::*;
 use futures::stream::FuturesOrdered;
@@ -44,6 +44,18 @@ use tracing::{debug, trace, warn};
 /// ```rust
 /// # use bastion::prelude::*;
 /// #
+/// # #[cfg(feature = "tokio-runtime")]
+/// # #[tokio::main]
+/// # async fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # #[cfg(not(feature = "tokio-runtime"))]
+/// # fn main() {
+/// #    run();    
+/// # }
+/// #
+/// # fn run() {
 /// # Bastion::init();
 /// #
 /// let sp_ref: SupervisorRef = Bastion::supervisor(|sp| {
@@ -55,12 +67,11 @@ use tracing::{debug, trace, warn};
 /// # Bastion::start();
 /// # Bastion::stop();
 /// # Bastion::block_until_stopped();
+/// # }
 /// ```
 ///
-/// [`Children`]: children/struct.Children.html
-/// [`SupervisionStrategy`]: supervisor/enum.SupervisionStrategy.html
-/// [`with_strategy`]: #method.with_strategy
-/// [`Bastion::children`]: struct.Bastion.html#method.children
+/// [`Bastion::children`]: crate::Bastion::children
+/// [`with_strategy`]: Self::with_strategy
 pub struct Supervisor {
     bcast: Broadcast,
     // The order in which children and supervisors were added.
@@ -106,7 +117,7 @@ pub struct Supervisor {
 #[derive(Debug, Clone)]
 struct TrackedChildState {
     id: BastionId,
-    state: Arc<Mutex<Pin<Box<ContextState>>>>,
+    state: Arc<Pin<Box<ContextState>>>,
     restarts_counts: usize,
 }
 
@@ -127,7 +138,7 @@ enum ActorSearchMethod {
 /// A "reference" to a [`Supervisor`], allowing to
 /// communicate with it.
 ///
-/// [`Supervisor`]: supervisor/struct.Supervisor.html
+// [`Supervisor`]: supervisor/struct.Supervisor.html
 pub struct SupervisorRef {
     id: BastionId,
     sender: Sender,
@@ -187,8 +198,8 @@ pub enum RestartPolicy {
 /// restoring failed actors. It it fails after N attempts,
 /// the supervisor will remove an actor.
 ///
-/// The default strategy used is `ActorRestartStrategy::Immediate`
-/// with the `RestartPolicy::Always` restart policy.
+/// The default strategy used is [`ActorRestartStrategy::Immediate`]
+/// with the [`RestartPolicy::Always`] restart policy.
 #[derive(Debug, Clone, PartialEq)]
 pub struct RestartStrategy {
     restart_policy: RestartPolicy,
@@ -199,7 +210,9 @@ pub struct RestartStrategy {
 /// The strategy for restating an actor as far as it
 /// returned an failure.
 ///
-/// The default strategy is `Immediate`.
+/// The default strategy is [`Immediate`].
+///
+/// [`Immediate`]: ActorRestartStrategy::Immediate
 pub enum ActorRestartStrategy {
     /// Restart an actor as soon as possible, since the moment
     /// the actor finished with a failure.
@@ -358,6 +371,18 @@ impl Supervisor {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::supervisor(|sp| {
@@ -370,6 +395,7 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn id(&self) -> &BastionId {
         &self.bcast.id()
@@ -414,6 +440,18 @@ impl Supervisor {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|parent| {
@@ -427,10 +465,10 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`SupervisorRef`]: ../struct.SupervisorRef.html
-    /// [`supervisor_ref`]: #method.supervisor_ref
+    /// [`supervisor_ref`]: Self::supervisor_ref
     pub fn supervisor<S>(self, init: S) -> Self
     where
         S: FnOnce(Supervisor) -> Supervisor,
@@ -477,6 +515,18 @@ impl Supervisor {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|mut parent| {
@@ -491,10 +541,10 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`SupervisorRef`]: ../struct.SupervisorRef.html
-    /// [`supervisor`]: #method.supervisor
+    /// [`supervisor`]: Self::supervisor
     pub fn supervisor_ref<S>(&mut self, init: S) -> SupervisorRef
     where
         S: FnOnce(Supervisor) -> Supervisor,
@@ -542,6 +592,18 @@ impl Supervisor {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|sp| {
@@ -563,11 +625,12 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`Children`]: children/struct.Children.html
-    /// [`ChildrenRef`]: children/struct.ChildrenRef.html
-    /// [`children_ref`]: #method.children_ref
+    // [`Children`]: children/struct.Children.html
+    // [`ChildrenRef`]: children/struct.ChildrenRef.html
+    /// [`children_ref`]: Self::children_ref
     pub fn children<C>(self, init: C) -> Self
     where
         C: FnOnce(Children) -> Children,
@@ -584,10 +647,18 @@ impl Supervisor {
         let children = Children::new(bcast);
         let mut children = init(children);
         debug!("Children({}): Initialized.", children.id());
+
         // FIXME: children group elems launched without the group itself being launched
         if let Err(e) = children.register_dispatchers() {
             warn!("couldn't register all dispatchers into the registry: {}", e);
         };
+        if let Err(e) = children.register_distributors() {
+            warn!(
+                "couldn't register all distributors into the registry: {}",
+                e
+            );
+        };
+
         children.launch_elems();
 
         debug!(
@@ -619,6 +690,18 @@ impl Supervisor {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # Bastion::supervisor(|mut sp| {
@@ -641,11 +724,10 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     ///
-    /// [`Children`]: children/struct.Children.html
-    /// [`ChildrenRef`]: children/struct.ChildrenRef.html
-    /// [`children`]: #method.children
+    /// [`children`]: Self::children
     pub fn children_ref<C>(&self, init: C) -> ChildrenRef
     where
         C: FnOnce(Children) -> Children,
@@ -708,6 +790,18 @@ impl Supervisor {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::supervisor(|sp| {
@@ -718,11 +812,8 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`SupervisionStrategy::OneForOne`]: supervisor/enum.SupervisionStrategy.html#variant.OneForOne
-    /// [`SupervisionStrategy::OneForAll`]: supervisor/enum.SupervisionStrategy.html#variant.OneForAll
-    /// [`SupervisionStrategy::RestForOne`]: supervisor/enum.SupervisionStrategy.html#variant.RestForOne
     pub fn with_strategy(mut self, strategy: SupervisionStrategy) -> Self {
         trace!(
             "Supervisor({}): Setting strategy: {:?}",
@@ -746,6 +837,18 @@ impl Supervisor {
     /// # use bastion::prelude::*;
     /// # use std::time::Duration;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// # Bastion::supervisor(|sp| {
     /// sp.with_restart_strategy(
@@ -763,6 +866,7 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn with_restart_strategy(mut self, restart_strategy: RestartStrategy) -> Self {
         trace!(
@@ -790,6 +894,18 @@ impl Supervisor {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// Bastion::supervisor(|sp| {
@@ -803,9 +919,8 @@ impl Supervisor {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Callbacks`]: struct.Callbacks.html
     pub fn with_callbacks(mut self, callbacks: Callbacks) -> Self {
         trace!(
             "Supervisor({}): Setting callbacks: {:?}",
@@ -1400,6 +1515,18 @@ impl SupervisorRef {
     /// ```rust
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// let supervisor_ref = Bastion::supervisor(|sp| {
@@ -1412,6 +1539,7 @@ impl SupervisorRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn id(&self) -> &BastionId {
         &self.id
@@ -1435,6 +1563,18 @@ impl SupervisorRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let mut parent_ref = Bastion::supervisor(|sp| sp).unwrap();
@@ -1447,9 +1587,8 @@ impl SupervisorRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Supervisor`]: supervisor/struct.Supervisor.html
     pub fn supervisor<S>(&self, init: S) -> Result<Self, ()>
     where
         S: FnOnce(Supervisor) -> Supervisor,
@@ -1485,7 +1624,7 @@ impl SupervisorRef {
     /// `SupervisorRef` is referencing to supervise it.
     ///
     /// This methods returns a [`ChildrenRef`] referencing the newly
-    /// created children group it it succeeded, or `Err(())`
+    /// created children group if it succeeded, or `Err(())`
     /// otherwise.
     ///
     /// # Arguments
@@ -1498,6 +1637,18 @@ impl SupervisorRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let sp_ref = Bastion::supervisor(|sp| sp).unwrap();
@@ -1518,10 +1669,8 @@ impl SupervisorRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`Children`]: children/struct.Children.html
-    /// [`ChildrenRef`]: children/struct.ChildrenRef.html
     pub fn children<C>(&self, init: C) -> Result<ChildrenRef, ()>
     where
         C: FnOnce(Children) -> Children,
@@ -1596,6 +1745,18 @@ impl SupervisorRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let sp_ref = Bastion::supervisor(|sp| sp).unwrap();
@@ -1605,11 +1766,8 @@ impl SupervisorRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
-    ///
-    /// [`SupervisionStrategy::OneForOne`]: supervisor/enum.SupervisionStrategy.html#variant.OneForOne
-    /// [`SupervisionStrategy::OneForAll`]: supervisor/enum.SupervisionStrategy.html#variant.OneForAll
-    /// [`SupervisionStrategy::RestForOne`]: supervisor/enum.SupervisionStrategy.html#variant.RestForOne
     pub fn strategy(&self, strategy: SupervisionStrategy) -> Result<(), ()> {
         debug!(
             "SupervisorRef({}): Setting strategy: {:?}",
@@ -1637,7 +1795,18 @@ impl SupervisorRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
     /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     ///     # Bastion::init();
     ///     #
     ///     # let sp_ref = Bastion::supervisor(|sp| sp).unwrap();
@@ -1693,6 +1862,18 @@ impl SupervisorRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let sp_ref = Bastion::supervisor(|sp| sp).unwrap();
@@ -1701,6 +1882,7 @@ impl SupervisorRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn stop(&self) -> Result<(), ()> {
         debug!("SupervisorRef({}): Stopping.", self.id());
@@ -1721,6 +1903,18 @@ impl SupervisorRef {
     /// ```
     /// # use bastion::prelude::*;
     /// #
+    /// # #[cfg(feature = "tokio-runtime")]
+    /// # #[tokio::main]
+    /// # async fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # #[cfg(not(feature = "tokio-runtime"))]
+    /// # fn main() {
+    /// #    run();    
+    /// # }
+    /// #
+    /// # fn run() {
     /// # Bastion::init();
     /// #
     /// # let sp_ref = Bastion::supervisor(|sp| sp).unwrap();
@@ -1729,6 +1923,7 @@ impl SupervisorRef {
     /// # Bastion::start();
     /// # Bastion::stop();
     /// # Bastion::block_until_stopped();
+    /// # }
     /// ```
     pub fn kill(&self) -> Result<(), ()> {
         debug!("SupervisorRef({}): Killing.", self.id());
@@ -1750,7 +1945,7 @@ impl SupervisorRef {
 }
 
 impl TrackedChildState {
-    fn new(id: BastionId, state: Arc<Mutex<Pin<Box<ContextState>>>>) -> Self {
+    fn new(id: BastionId, state: Arc<Pin<Box<ContextState>>>) -> Self {
         TrackedChildState {
             id,
             state,
@@ -1762,7 +1957,7 @@ impl TrackedChildState {
         self.id.clone()
     }
 
-    fn state(&self) -> Arc<Mutex<Pin<Box<ContextState>>>> {
+    fn state(&self) -> Arc<Pin<Box<ContextState>>> {
         self.state.clone()
     }
 
@@ -1845,11 +2040,11 @@ impl RestartStrategy {
     /// # Arguments
     ///
     /// * `restart_policy` - Defines a restart policy to use for failed actor:
-    ///     - [`RestartStrategy::Always`] would restart the
+    ///     - [`RestartPolicy::Always`] would restart the
     ///         failed actor each time as it fails.
-    ///     - [`RestartStrategy::Never`] would not restart the
+    ///     - [`RestartPolicy::Never`] would not restart the
     ///         failed actor and remove it from tracking.
-    ///     - [`RestartStrategy::Tries`] would restart the
+    ///     - [`RestartPolicy::Tries`] would restart the
     ///         failed actor a limited amount of times. If can't be started,
     ///         then will remove it from tracking.   
     ///
@@ -1873,13 +2068,6 @@ impl RestartStrategy {
     /// let restart_strategy = RestartStrategy::default()
     ///     .with_actor_restart_strategy(actor_restart_strategy);
     /// ```
-    ///
-    /// [`RestartStrategy::Always`]: enum.RestartPolicy.html#variant.Always
-    /// [`RestartStrategy::Never`]: enum.RestartPolicy.html#variant.Never
-    /// [`RestartStrategy::Tries`]: enum.RestartPolicy.html#variant.Tries
-    /// [`ActorRestartStrategy::Immediate`]: enum.ActorRestartStrategy.html#variant.Immediate
-    /// [`ActorRestartStrategy::LinearBackOff`]: enum.ActorRestartStrategy.html#variant.LinearBackOff
-    /// [`ActorRestartStrategy::ExponentialBackOff`]: enum.ActorRestartStrategy.html#variant.ExponentialBackOff
     pub fn new(restart_policy: RestartPolicy, strategy: ActorRestartStrategy) -> Self {
         RestartStrategy {
             restart_policy,
diff --git a/src/bastion/src/system/global_state.rs b/src/bastion/src/system/global_state.rs
new file mode 100644
index 00000000..0758e152
--- /dev/null
+++ b/src/bastion/src/system/global_state.rs
@@ -0,0 +1,196 @@
+use std::sync::Arc;
+/// This module contains implementation of the global state that
+/// available to all actors in runtime. To provide safety and avoid
+/// data races, the implementation is heavily relies on software
+/// transaction memory (or shortly STM) mechanisms to eliminate any
+/// potential data races and provide consistency across actors.
+use std::{
+    any::{Any, TypeId},
+    sync::RwLock,
+};
+use std::{collections::hash_map::Entry, ops::Deref};
+
+use lever::sync::atomics::AtomicBox;
+use lever::table::lotable::LOTable;
+use lightproc::proc_state::AsAny;
+use std::collections::HashMap;
+
+use crate::errors::{BastionError, BastionResult};
+
+#[derive(Debug)]
+pub struct GlobalState {
+    table: Arc<RwLock<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>>, // todo: remove the arc<rwlock< once we figure it out
+}
+
+impl GlobalState {
+    /// Returns a new instance of global state.
+    pub(crate) fn new() -> Self {
+        GlobalState {
+            table: Arc::new(RwLock::new(HashMap::new())),
+        }
+    }
+
+    /// Inserts the given value in the global state. If the value
+    /// exists, it will be overridden.
+    pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) -> bool {
+        self.table
+            .write()
+            .unwrap()
+            .insert(
+                TypeId::of::<T>(),
+                Arc::new(value) as Arc<dyn Any + Send + Sync>,
+            )
+            .is_some()
+    }
+
+    /// Invokes a function with the requested data type.
+    pub fn read<T: Send + Sync + 'static>(&mut self, f: impl FnOnce(Option<&T>)) {
+        self.table
+            .read()
+            .unwrap()
+            .get(&TypeId::of::<T>())
+            .map(|value| f(value.downcast_ref()));
+    }
+
+    /// Invokes a function with the requested data type.
+    pub fn write<T: std::fmt::Debug + Send + Sync + 'static, F>(&mut self, f: F)
+    where
+        F: Fn(Option<&T>) -> Option<T>,
+    {
+        let mut hm = self.table.write().unwrap();
+        let stuff_to_insert = match hm.entry(TypeId::of::<T>()) {
+            Entry::Occupied(data) => f(data.get().downcast_ref()),
+            Entry::Vacant(_) => f(None),
+        };
+
+        if let Some(stuff) = stuff_to_insert {
+            hm.insert(
+                TypeId::of::<T>(),
+                Arc::new(stuff) as Arc<dyn Any + Send + Sync>,
+            );
+        } else {
+            hm.remove(&TypeId::of::<T>());
+        };
+    }
+
+    /// Checks the given values is storing in the global state.
+    pub fn contains<T: Send + Sync + 'static>(&self) -> bool {
+        self.table.read().unwrap().contains_key(&TypeId::of::<T>())
+    }
+
+    /// Deletes the entry from the global state.
+    pub fn remove<T: Send + Sync + 'static>(&mut self) -> bool {
+        self.table
+            .write()
+            .unwrap()
+            .remove(&TypeId::of::<T>())
+            .is_some()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::system::global_state::GlobalState;
+
+    #[derive(Clone, Debug, Eq, PartialEq)]
+    struct TestData {
+        counter: u64,
+    }
+
+    #[test]
+    fn test_insert() {
+        let mut instance = GlobalState::new();
+        let test_data = TestData { counter: 0 };
+
+        instance.insert(test_data.clone());
+        assert_eq!(instance.contains::<TestData>(), true);
+    }
+
+    #[test]
+    fn test_insert_with_overriding_data() {
+        let mut instance = GlobalState::new();
+
+        let first_insert_data = TestData { counter: 0 };
+        instance.insert(first_insert_data.clone());
+        assert_eq!(instance.contains::<TestData>(), true);
+
+        let second_insert_data = TestData { counter: 1 };
+        instance.insert(second_insert_data.clone());
+        assert_eq!(instance.contains::<TestData>(), true);
+    }
+
+    #[test]
+    fn test_contains_returns_true() {
+        let mut instance = GlobalState::new();
+        assert_eq!(instance.contains::<TestData>(), false);
+
+        instance.insert(TestData { counter: 0 });
+        assert_eq!(instance.contains::<TestData>(), true);
+    }
+
+    #[test]
+    fn test_contains_returns_false() {
+        let instance = GlobalState::new();
+
+        assert_eq!(instance.contains::<usize>(), false);
+    }
+
+    #[test]
+    fn test_remove_returns_true() {
+        let mut instance = GlobalState::new();
+
+        instance.insert(TestData { counter: 0 });
+        assert_eq!(instance.contains::<TestData>(), true);
+
+        let is_removed = instance.remove::<TestData>();
+        assert_eq!(is_removed, true);
+    }
+
+    #[test]
+    fn test_remove_returns_false() {
+        let mut instance = GlobalState::new();
+
+        let is_removed = instance.remove::<usize>();
+        assert_eq!(is_removed, false);
+    }
+
+    #[test]
+    fn test_write_read() {
+        let mut instance = GlobalState::new();
+
+        #[derive(Debug, PartialEq, Clone)]
+        struct Hello {
+            foo: bool,
+            bar: usize,
+        }
+
+        let expected = Hello { foo: true, bar: 42 };
+
+        instance.insert(expected.clone());
+
+        instance.read(|actual: Option<&Hello>| {
+            assert_eq!(&expected, actual.unwrap());
+        });
+
+        let expected_updated = Hello {
+            foo: false,
+            bar: 43,
+        };
+
+        instance.write::<Hello, _>(|maybe_to_update| {
+            let to_update = maybe_to_update.unwrap();
+
+            let updated = Hello {
+                foo: !to_update.foo,
+                bar: to_update.bar + 1,
+            };
+
+            Some(updated)
+        });
+
+        instance.read(|updated: Option<&Hello>| {
+            let updated = updated.unwrap();
+            assert_eq!(updated, &expected_updated);
+        });
+    }
+}
diff --git a/src/bastion/src/system/mod.rs b/src/bastion/src/system/mod.rs
new file mode 100644
index 00000000..373dd204
--- /dev/null
+++ b/src/bastion/src/system/mod.rs
@@ -0,0 +1,7 @@
+mod global_state;
+mod node;
+
+use crate::system::node::Node;
+use once_cell::sync::Lazy;
+
+pub static SYSTEM: Lazy<Node> = Lazy::new(Node::new);
diff --git a/src/bastion/src/system/node.rs b/src/bastion/src/system/node.rs
new file mode 100644
index 00000000..5c77e368
--- /dev/null
+++ b/src/bastion/src/system/node.rs
@@ -0,0 +1,29 @@
+use crate::system::global_state::GlobalState;
+
+#[derive(Debug)]
+/// An implementation of the Bastion's node. By default
+/// it's available as a singleton object. The node stores all
+/// required information for running various actor implementations,
+///
+/// Out-of-the-box it also provides:
+/// - Adding actor definitions in runtime
+/// - API for starting, stopping or terminating actors
+/// - Global state available to all actors
+/// - Message dispatching
+///
+pub struct Node {
+    global_state: GlobalState,
+}
+
+impl Node {
+    /// Returns a new instance of the Bastion Node.
+    pub(crate) fn new() -> Self {
+        let global_state = GlobalState::new();
+
+        Node { global_state }
+    }
+
+    // TODO: Add errors handling?
+    /// Initializes the Bastion node if it hasn't already been done.
+    pub async fn init(&self) {}
+}
diff --git a/src/bastion/tests/message_signatures.rs b/src/bastion/tests/message_signatures.rs
index d4131fe7..6c107725 100644
--- a/src/bastion/tests/message_signatures.rs
+++ b/src/bastion/tests/message_signatures.rs
@@ -19,7 +19,7 @@ fn spawn_responders() -> ChildrenRef {
             msg! { ctx.recv().await?,
                 msg: &'static str =!> {
                     if msg == "Hello" {
-                            assert!(signature!().is_sender_identified(), false);
+                            assert!(signature!().is_sender_identified(), "sender is not identified");
                             answer!(ctx, "Goodbye").unwrap();
                     }
                 };
@@ -42,11 +42,28 @@ fn spawn_responders() -> ChildrenRef {
     .expect("Couldn't create the children group.")
 }
 
-#[test]
-fn answer_and_tell_signatures() {
-    setup();
-    Bastion::spawn(run).unwrap();
-    teardown();
+#[cfg(feature = "tokio-runtime")]
+mod tokio_tests {
+    use super::*;
+
+    #[tokio::test]
+    async fn answer_and_tell_signatures() {
+        setup();
+        Bastion::spawn(run).unwrap();
+        teardown();
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod no_tokio_tests {
+    use super::*;
+
+    #[test]
+    fn answer_and_tell_signatures() {
+        setup();
+        Bastion::spawn(run).unwrap();
+        teardown();
+    }
 }
 
 async fn run(ctx: BastionContext) -> Result<(), ()> {
diff --git a/src/bastion/tests/prop_children_broadcast.proptest-regressions b/src/bastion/tests/prop_children_broadcast.proptest-regressions
new file mode 100644
index 00000000..0581f2f2
--- /dev/null
+++ b/src/bastion/tests/prop_children_broadcast.proptest-regressions
@@ -0,0 +1,8 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+cc 70c25a250dab8458e4c6eced0bd8d0b0925a85cab0e33fe71a3c527b8b3780c2 # shrinks to message = ""
+cc 0ce425dcb58b6d604391a2b073f13559ce8e882abe9aeaa760fe7c97b2f5d610 # shrinks to message = "\u{10a39}🢰ûѨ*� .﹪/3t\\ஞ0\"Ⱥ\'ቒ1"
diff --git a/src/bastion/tests/prop_children_broadcast.rs b/src/bastion/tests/prop_children_broadcast.rs
index 12216e3b..df072d81 100644
--- a/src/bastion/tests/prop_children_broadcast.rs
+++ b/src/bastion/tests/prop_children_broadcast.rs
@@ -4,32 +4,53 @@ use std::sync::Once;
 
 static START: Once = Once::new();
 
-proptest! {
-    #![proptest_config(ProptestConfig::with_cases(1_000))]
-    #[test]
-    fn proptest_bcast_message(message in "\\PC*") {
-        START.call_once(|| {
-            Bastion::init();
-        });
-        Bastion::start();
-
-        if let Ok(_chrn) = Bastion::children(|children: Children| {
-            children
-                .with_exec(move |ctx: BastionContext| {
-                    async move {
-                        msg! { ctx.recv().await?,
-                            ref _msg: &'static str => {};
-                            // This won't happen because this example
-                            // only "asks" a `&'static str`...
-                            _: _ => {};
-                        }
+#[cfg(feature = "tokio-runtime")]
+mod tokio_proptests {
+    use super::*;
+    proptest! {
+        #![proptest_config(ProptestConfig::with_cases(1_000))]
+        #[test]
+        fn proptest_bcast_message(message in "\\PC*") {
+            tokio_test::block_on(async {
+                super::test_with_message(message);
+            });
+        }
+    }
+}
+#[cfg(not(feature = "tokio-runtime"))]
+mod not_tokio_proptests {
+    use super::*;
 
-                        Ok(())
-                    }
-                })
-        }){
-            let message: &'static str = Box::leak(message.into_boxed_str());
-            Bastion::broadcast(message).expect("broadcast failed");
+    proptest! {
+        #![proptest_config(ProptestConfig::with_cases(1_000))]
+        #[test]
+        fn proptest_bcast_message(message in "\\PC*") {
+            super::test_with_message(message);
         }
     }
 }
+
+fn test_with_message(message: String) {
+    START.call_once(|| {
+        Bastion::init();
+    });
+    Bastion::start();
+
+    if let Ok(_chrn) = Bastion::children(|children: Children| {
+        children.with_exec(move |ctx: BastionContext| {
+            async move {
+                msg! { ctx.recv().await?,
+                    ref _msg: &'static str => {};
+                    // This won't happen because this example
+                    // only "asks" a `&'static str`...
+                    _: _ => {};
+                }
+
+                Ok(())
+            }
+        })
+    }) {
+        let message: &'static str = Box::leak(message.into_boxed_str());
+        Bastion::broadcast(message).expect("broadcast failed");
+    }
+}
diff --git a/src/bastion/tests/prop_children_message.proptest-regressions b/src/bastion/tests/prop_children_message.proptest-regressions
new file mode 100644
index 00000000..0b089acd
--- /dev/null
+++ b/src/bastion/tests/prop_children_message.proptest-regressions
@@ -0,0 +1,7 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+cc 8428d777018d9727329e319192aecdc1187db6917e2a518fd7fd2e285cae0d8d # shrinks to message = ""
diff --git a/src/bastion/tests/prop_children_message.rs b/src/bastion/tests/prop_children_message.rs
index ba2ea5f2..d6278fb1 100644
--- a/src/bastion/tests/prop_children_message.rs
+++ b/src/bastion/tests/prop_children_message.rs
@@ -5,42 +5,65 @@ use std::sync::Once;
 
 static START: Once = Once::new();
 
-proptest! {
-    #![proptest_config(ProptestConfig::with_cases(1_000))]
-    #[test]
-    fn proptest_intra_message(message in "\\PC*") {
-        START.call_once(|| {
-            Bastion::init();
-        });
-        Bastion::start();
-
-        let message = Arc::new(message);
-
-        let _ = Bastion::children(|children| {
-            children
-                .with_exec(move |ctx: BastionContext| {
-                    let message = (*message).clone();
-                    async move {
-                        let message: &'static str = Box::leak(message.into_boxed_str());
-                        let answer = ctx
-                            .ask(&ctx.current().addr(), message)
-                            .expect("Couldn't send the message.");
-
-                        msg! { ctx.recv().await?,
-                            msg: &'static str =!> {
-                                let _ = answer!(ctx, msg);
-                            };
-                            _: _ => ();
-                        }
-
-                        msg! { answer.await?,
-                            _msg: &'static str => {};
-                            _: _ => {};
-                        }
-
-                        Ok(())
-                    }
-                })
-        });
+#[cfg(feature = "tokio-runtime")]
+mod tokio_proptests {
+    use super::*;
+    proptest! {
+        #![proptest_config(ProptestConfig::with_cases(1_000))]
+        #[test]
+        fn proptest_intra_message(message in "\\PC*") {
+            tokio::runtime::Runtime::new().unwrap().block_on(async {
+                super::test_with_message(message);
+
+            });
+        }
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod not_tokio_proptests {
+    use super::*;
+
+    proptest! {
+        #![proptest_config(ProptestConfig::with_cases(1_000))]
+        #[test]
+        fn proptest_intra_message(message in "\\PC*") {
+            super::test_with_message(message);
+        }
     }
 }
+
+fn test_with_message(message: String) {
+    START.call_once(|| {
+        Bastion::init();
+    });
+    Bastion::start();
+
+    let message = Arc::new(message);
+
+    let _ = Bastion::children(|children| {
+        children.with_exec(move |ctx: BastionContext| {
+            let message = (*message).clone();
+            async move {
+                let message: &'static str = Box::leak(message.into_boxed_str());
+                let answer = ctx
+                    .ask(&ctx.current().addr(), message)
+                    .expect("Couldn't send the message.");
+
+                msg! { ctx.recv().await?,
+                    msg: &'static str =!> {
+                        let _ = answer!(ctx, msg);
+                    };
+                    _: _ => ();
+                }
+
+                msg! { answer.await?,
+                    _msg: &'static str => {};
+                    _: _ => {};
+                }
+
+                Ok(())
+            }
+        })
+    });
+}
diff --git a/src/bastion/tests/prop_children_redundancy.proptest-regressions b/src/bastion/tests/prop_children_redundancy.proptest-regressions
new file mode 100644
index 00000000..3ed3661e
--- /dev/null
+++ b/src/bastion/tests/prop_children_redundancy.proptest-regressions
@@ -0,0 +1,8 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+cc 3133d59d522ffc52f22b079bc8288d5886ff9879d77ab2963132823345052892 # shrinks to r = 0
+cc 886d80a24e6a7e9241ad63841ded2f66f85d477041f292c5029542de1b38e40e # shrinks to r = 0
diff --git a/src/bastion/tests/prop_children_redundancy.rs b/src/bastion/tests/prop_children_redundancy.rs
index a5a03eb4..3d5ee508 100644
--- a/src/bastion/tests/prop_children_redundancy.rs
+++ b/src/bastion/tests/prop_children_redundancy.rs
@@ -4,30 +4,55 @@ use std::sync::Once;
 
 static START: Once = Once::new();
 
-proptest! {
-    #![proptest_config(ProptestConfig::with_cases(1_000))]
-    #[test]
-    fn proptest_redundancy(r in std::usize::MIN..32) {
-        START.call_once(|| {
-            Bastion::init();
-        });
-        Bastion::start();
+#[cfg(feature = "tokio-runtime")]
+mod tokio_proptests {
+    use super::*;
 
-        Bastion::children(|children| {
-            children
-                // shrink over the redundancy
-                .with_redundancy(r)
-                .with_exec(|_ctx: BastionContext| {
-                    async move {
-                        // It's a proptest,
-                        // we just don't want the loop
-                        // to be optimized away
-                        #[allow(clippy::drop_copy)]
-                        loop {
-                            std::mem::drop(());
-                        }
-                    }
-                })
-        }).expect("Coudn't spawn children.");
+    proptest! {
+        #![proptest_config(ProptestConfig::with_cases(1_000))]
+        #[test]
+        fn proptest_redundancy(r in std::usize::MIN..32) {
+            let _ = tokio_test::task::spawn(async {
+                super::test_with_usize(r);
+            });
+        }
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod not_tokio_proptests {
+    use super::*;
+
+    proptest! {
+        #![proptest_config(ProptestConfig::with_cases(1_000))]
+        #[test]
+        fn proptest_redundancy(r in std::usize::MIN..32) {
+            super::test_with_usize(r);
+        }
     }
 }
+
+fn test_with_usize(r: usize) {
+    START.call_once(|| {
+        Bastion::init();
+    });
+    Bastion::start();
+
+    Bastion::children(|children| {
+        children
+            // shrink over the redundancy
+            .with_redundancy(r)
+            .with_exec(|_ctx: BastionContext| {
+                async move {
+                    // It's a proptest,
+                    // we just don't want the loop
+                    // to be optimized away
+                    #[allow(clippy::drop_copy)]
+                    loop {
+                        std::mem::drop(());
+                    }
+                }
+            })
+    })
+    .expect("Coudn't spawn children.");
+}
diff --git a/src/bastion/tests/run_blocking.rs b/src/bastion/tests/run_blocking.rs
new file mode 100644
index 00000000..00ff3908
--- /dev/null
+++ b/src/bastion/tests/run_blocking.rs
@@ -0,0 +1,78 @@
+use bastion::prelude::*;
+use std::sync::{
+    atomic::{AtomicUsize, Ordering},
+    Arc,
+};
+use std::thread;
+use std::time::Duration;
+
+#[cfg(feature = "tokio-runtime")]
+mod tokio_tests {
+    #[tokio::test]
+    async fn test_run_blocking() {
+        super::run()
+    }
+}
+
+#[cfg(not(feature = "tokio-runtime"))]
+mod not_tokio_tests {
+    #[test]
+    fn test_run_blocking() {
+        super::run()
+    }
+}
+
+fn run() {
+    Bastion::init();
+    Bastion::start();
+
+    let c = Bastion::children(|children| {
+        // We are creating the function to exec
+        children.with_exec(|ctx: BastionContext| {
+            let received_messages = Arc::new(AtomicUsize::new(0));
+            async move {
+                let received_messages = Arc::clone(&received_messages);
+                loop {
+                    msg! {
+                        ctx.recv().await?,
+                        msg: &'static str =!>
+                         {
+                            assert_eq!(msg, "hello");
+                            let messages = received_messages.fetch_add(1, Ordering::SeqCst);
+                            answer!(ctx, messages + 1).expect("couldn't reply :(");
+                        };
+                        _: _ => panic!();
+                    }
+                }
+            }
+        })
+    })
+    .unwrap();
+
+    let child = c.elems()[0].clone();
+
+    let output = (0..100)
+        .map(|_| {
+            let child = child.clone();
+            run!(blocking!(
+                async move {
+                    let duration = Duration::from_millis(1);
+                    thread::sleep(duration);
+                    msg! {
+                        child.clone()
+                            .ask_anonymously("hello").unwrap().await.unwrap(),
+                            output: usize => output;
+                            _: _ => panic!();
+                    }
+                }
+                .await
+            ))
+            .unwrap()
+        })
+        .collect::<Vec<_>>();
+
+    Bastion::stop();
+    Bastion::block_until_stopped();
+
+    assert_eq!((1..=100).map(|i| i).collect::<Vec<_>>(), output);
+}
diff --git a/src/bastion/tests/tokio_runtime.rs b/src/bastion/tests/tokio_runtime.rs
new file mode 100644
index 00000000..4e7408c4
--- /dev/null
+++ b/src/bastion/tests/tokio_runtime.rs
@@ -0,0 +1,144 @@
+#[cfg(feature = "tokio-runtime")]
+mod tokio_tests {
+
+    use bastion::prelude::*;
+
+    #[tokio::test]
+    async fn test_simple_await() {
+        tokio::time::sleep(std::time::Duration::from_nanos(1)).await;
+    }
+
+    #[tokio::test]
+    async fn test_within_bastion() {
+        Bastion::init();
+        Bastion::start();
+
+        test_within_children().await;
+        test_within_message_receive().await;
+        test_within_message_receive_blocking().await;
+        test_within_message_receive_spawn().await;
+
+        Bastion::stop();
+    }
+
+    async fn test_within_children() {
+        Bastion::children(|children| {
+            children.with_exec(|_| async move {
+                tokio::time::sleep(std::time::Duration::from_nanos(1)).await;
+                Ok(())
+            })
+        })
+        .expect("Couldn't create the children group.");
+    }
+
+    async fn test_within_message_receive() {
+        let workers = Bastion::children(|children| {
+            children.with_exec(|ctx| async move {
+                msg! {
+                    ctx.recv().await?,
+                    question: &'static str =!> {
+                        if question != "marco" {
+                            panic!("didn't receive expected message");
+                        }
+                        tokio::time::sleep(std::time::Duration::from_nanos(1)).await;
+                        answer!(ctx, "polo").expect("couldn't send answer");
+                    };
+                    _: _ => {
+                        panic!("didn't receive &str");
+                    };
+                }
+                Ok(())
+            })
+        })
+        .expect("Couldn't create the children group.");
+
+        let answer = workers.elems()[0]
+            .ask_anonymously("marco")
+            .expect("Couldn't send the message.");
+
+        msg! { answer.await.expect("couldn't receive answer"),
+            reply: &'static str => {
+                if reply != "polo" {
+                    panic!("didn't receive expected message");
+                }
+            };
+            _: _ => { panic!("didn't receive &str"); };
+        }
+    }
+
+    async fn test_within_message_receive_blocking() {
+        let workers = Bastion::children(|children| {
+            children.with_exec(|ctx| async move {
+                msg! {
+                    ctx.recv().await?,
+                    question: &'static str =!> {
+                        if question != "marco" {
+                            panic!("didn't receive expected message");
+                        }
+                        run!(blocking! {
+                            let _ = tokio::time::sleep(std::time::Duration::from_nanos(1)).await;
+                            println!("done");
+                        });
+                        answer!(ctx, "polo").expect("couldn't send answer");
+                    };
+                    _: _ => {
+                        panic!("didn't receive &str");
+                    };
+                }
+                Ok(())
+            })
+        })
+        .expect("Couldn't create the children group.");
+
+        let answer = workers.elems()[0]
+            .ask_anonymously("marco")
+            .expect("Couldn't send the message.");
+
+        msg! { answer.await.expect("couldn't receive answer"),
+            reply: &'static str => {
+                if reply != "polo" {
+                    panic!("didn't receive expected message");
+                }
+            };
+            _: _ => { panic!("didn't receive &str"); };
+        }
+    }
+
+    async fn test_within_message_receive_spawn() {
+        let workers = Bastion::children(|children| {
+            children.with_exec(|ctx| async move {
+                msg! {
+                    ctx.recv().await?,
+                    question: &'static str =!> {
+                        if question != "marco" {
+                            panic!("didn't receive expected message");
+                        }
+                        run!(blocking! {
+                            let _ = tokio::time::sleep(std::time::Duration::from_nanos(1)).await;
+                            println!("done");
+                        });
+                        answer!(ctx, "polo").expect("couldn't send answer");
+                    };
+                    _: _ => {
+                        panic!("didn't receive &str");
+                    };
+                }
+                Ok(())
+            })
+        })
+        .expect("Couldn't create the children group.");
+
+        let answer = workers.elems()[0]
+            .ask_anonymously("marco")
+            .expect("Couldn't send the message.");
+
+        msg! { answer.await.expect("couldn't receive answer"),
+            reply: &'static str => {
+                if reply != "polo" {
+                    panic!("didn't receive expected message");
+                }
+            };
+            _: _ => { panic!("didn't receive &str"); };
+        }
+    }
+}
diff --git a/src/lightproc/Cargo.toml b/src/lightproc/Cargo.toml
index 50254302..282efd7c 100644
--- a/src/lightproc/Cargo.toml
+++ b/src/lightproc/Cargo.toml
@@ -16,10 +16,10 @@ edition = "2018"
 maintenance = { status = "actively-developed" }
 
 [dependencies]
-crossbeam-utils = "0.7"
+crossbeam-utils = "0.8"
 pin-utils = "0.1.0"
 
 [dev-dependencies]
-crossbeam = "0.7"
+crossbeam = "0.8"
 futures-executor = "0.3"
 lazy_static = "1.4.0"
diff --git a/tools/miri.sh b/tools/miri.sh
new file mode 100755
index 00000000..e0775f44
--- /dev/null
+++ b/tools/miri.sh
@@ -0,0 +1,10 @@
+rustup component add miri
+cargo miri setup
+cargo clean
+# Do some Bastion shake
+pushd src/bastion && \
+    MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks" cargo miri test --features lever/nightly dispatcher && \
+    MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks" cargo miri test --features lever/nightly path && \
+    MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks" cargo miri test --features lever/nightly broadcast && \
+    MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks" cargo miri test --features lever/nightly children_ref && \
+popd