diff --git a/speedy/.gitignore b/speedy/.gitignore
index f47cb2045..bd250b222 100644
--- a/speedy/.gitignore
+++ b/speedy/.gitignore
@@ -1 +1,4 @@
 *.out
+*.dSYM/
+*.gdb
+.gdb_history
diff --git a/speedy/Makefile b/speedy/Makefile
index caecf5cfc..98078a83b 100644
--- a/speedy/Makefile
+++ b/speedy/Makefile
@@ -1,7 +1,8 @@
 CXX=clang++
 CFLAGS=-std=c++11 -Wall
-LDFLAGS=-luv -lhttp_parser
-INC=-I../
+LDFLAGS=-luv -lhttp_parser -lr3
+# debug only
+INC=-I../ -g -O0 -fno-inline-functions
 SOURCES=$(wildcard *.cpp)
 EXECUTABLE=test.out
 # OBJECTS=$(SOURCES:.cpp=.o)
diff --git a/speedy/README.md b/speedy/README.md
index 36ef6b25e..19edc5494 100644
--- a/speedy/README.md
+++ b/speedy/README.md
@@ -21,5 +21,11 @@ make install
 * https://github.com/c9s/r3
 
 ```
-brew install r3 (OSX)
+./autogen.sh
+./configure
+make
+sudo make install
 ```
+
+## NOTE
+r3_include.h is custom r3 header file because of compilation problem related to redefinition of bool
diff --git a/speedy/r3_include.h b/speedy/r3_include.h
new file mode 100644
index 000000000..1fe192047
--- /dev/null
+++ b/speedy/r3_include.h
@@ -0,0 +1,228 @@
+/*
+ * r3.h
+ * Copyright (C) 2014 c9s <yoanlin93@gmail.com>
+ *
+ * Distributed under terms of the MIT license.
+ */
+#ifndef R3_NODE_H
+#define R3_NODE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pcre.h>
+#include <stdbool.h>
+#include <r3/str_array.h>
+#include <r3/r3_str.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _edge;
+struct _node;
+struct _route;
+typedef struct _edge edge;
+typedef struct _node node;
+typedef struct _route route;
+
+struct _node {
+    edge  ** edges;
+    // edge  ** edge_table;
+
+    // edges are mostly less than 255
+    unsigned char    compare_type; // compare_type: pcre, opcode, string
+    unsigned char    edge_len;
+    unsigned char    endpoint; // endpoint, should be zero for non-endpoint nodes
+    unsigned char    ov_cnt; // capture vector array size for pcre
+
+    // almost less than 255
+    unsigned char      edge_cap;
+    unsigned char      route_len;
+    unsigned char      route_cap;
+    // <-- here comes a char[1] struct padding for alignment since we have 4 char above.
+
+
+    /** compile-time variables here.... **/
+
+    /* the combined regexp pattern string from pattern_tokens */
+    pcre * pcre_pattern;
+    pcre_extra * pcre_extra;
+
+    route ** routes;
+
+    char * combined_pattern;
+
+    /**
+     * the pointer of route data
+     */
+    void * data;
+};
+
+#define r3_node_edge_pattern(node,i) node->edges[i]->pattern
+#define r3_node_edge_pattern_len(node,i) node->edges[i]->pattern_len
+
+struct _edge {
+    char * pattern; // 8 bytes
+    node * child; // 8 bytes
+    unsigned char  pattern_len; // 1 byte
+    unsigned char  opcode:4; // 4 bit
+    unsigned char  has_slug:1; // 1 bit
+};
+
+struct _route {
+    char * path;
+    int    path_len;
+
+    int    request_method; // can be (GET || POST)
+
+    char * host; // required host name
+    int    host_len;
+
+    void * data;
+
+    char * remote_addr_pattern;
+    int    remote_addr_pattern_len;
+};
+
+typedef struct {
+    str_array * vars;
+    const char * path; // current path to dispatch
+    int    path_len; // the length of the current path
+    int    request_method;  // current request method
+
+    void * data; // route ptr
+
+    char * host; // the request host
+    int    host_len;
+
+    char * remote_addr;
+    int    remote_addr_len;
+} match_entry;
+
+
+
+
+
+
+
+
+node * r3_tree_create(int cap);
+
+node * r3_node_create();
+
+void r3_tree_free(node * tree);
+
+edge * r3_node_connectl(node * n, const char * pat, int len, int strdup, node *child);
+
+#define r3_node_connect(n, pat, child) r3_node_connectl(n, pat, strlen(pat), 0, child)
+
+edge * r3_node_find_edge(const node * n, const char * pat, int pat_len);
+
+void r3_node_append_edge(node *n, edge *child);
+
+
+edge * r3_node_find_common_prefix(node *n, const char *path, int path_len, int *prefix_len, char **errstr);
+
+node * r3_tree_insert_pathl(node *tree, const char *path, int path_len, void * data);
+
+#define r3_tree_insert_pathl(tree, path, path_len, data) r3_tree_insert_pathl_ex(tree, path, path_len, NULL , data, NULL)
+
+
+
+route * r3_tree_insert_routel(node *tree, int method, const char *path, int path_len, void *data);
+
+route * r3_tree_insert_routel_ex(node *tree, int method, const char *path, int path_len, void *data, char **errstr);
+
+#define r3_tree_insert_routel(n, method, path, path_len, data) r3_tree_insert_routel_ex(n, method, path, path_len, data, NULL)
+
+#define r3_tree_insert_path(n,p,d) r3_tree_insert_pathl_ex(n,p,strlen(p), NULL, d, NULL)
+
+#define r3_tree_insert_route(n,method,path,data) r3_tree_insert_routel(n, method, path, strlen(path), data)
+
+
+/**
+ * The private API to insert a path
+ */
+node * r3_tree_insert_pathl_ex(node *tree, const char *path, int path_len, route * route, void * data, char ** errstr);
+
+void r3_tree_dump(const node * n, int level);
+
+
+edge * r3_node_find_edge_str(const node * n, const char * str, int str_len);
+
+
+int r3_tree_compile(node *n, char** errstr);
+
+int r3_tree_compile_patterns(node * n, char** errstr);
+
+node * r3_tree_matchl(const node * n, const char * path, int path_len, match_entry * entry);
+
+#define r3_tree_match(n,p,e)  r3_tree_matchl(n,p, strlen(p), e)
+
+// node * r3_tree_match_entry(node * n, match_entry * entry);
+#define r3_tree_match_entry(n, entry) r3_tree_matchl(n, entry->path, entry->path_len, entry)
+
+bool r3_node_has_slug_edges(const node *n);
+
+edge * r3_edge_createl(const char * pattern, int pattern_len, node * child);
+
+node * r3_edge_branch(edge *e, int dl);
+
+void r3_edge_free(edge * edge);
+
+
+
+
+
+route * r3_route_create(const char * path);
+
+route * r3_route_createl(const char * path, int path_len);
+
+
+void r3_node_append_route(node * n, route * route);
+
+void r3_route_free(route * route);
+
+int r3_route_cmp(const route *r1, const match_entry *r2);
+
+route * r3_tree_match_route(const node *n, match_entry * entry);
+
+#define r3_route_create(p) r3_route_createl(p, strlen(p))
+
+
+#define METHOD_GET 2
+#define METHOD_POST 2<<1
+#define METHOD_PUT 2<<2
+#define METHOD_DELETE 2<<3
+#define METHOD_PATCH 2<<4
+#define METHOD_HEAD 2<<5
+#define METHOD_OPTIONS 2<<6
+
+
+
+int r3_pattern_to_opcode(const char * pattern, int pattern_len);
+
+enum { NODE_COMPARE_STR, NODE_COMPARE_PCRE, NODE_COMPARE_OPCODE };
+
+enum { OP_EXPECT_MORE_DIGITS = 1, OP_EXPECT_MORE_WORDS, OP_EXPECT_NOSLASH, OP_EXPECT_NODASH, OP_EXPECT_MORE_ALPHA };
+
+
+
+match_entry * match_entry_createl(const char * path, int path_len);
+
+#define match_entry_create(path) match_entry_createl(path,strlen(path))
+
+void match_entry_free(match_entry * entry);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif /* !R3_NODE_H */
diff --git a/speedy/speedy.hpp b/speedy/speedy.hpp
index a208aee5a..cc17b7bd5 100644
--- a/speedy/speedy.hpp
+++ b/speedy/speedy.hpp
@@ -1,22 +1,32 @@
 #ifndef MEMGRAPH_SPEEDY_HPP
 #define MEMGRAPH_SPEEDY_HPP
 
+#include <vector>
+
 #include "io/uv/uv.hpp"
 #include "http/http.hpp"
+#include "r3_include.h"
 
 namespace speedy
 {
 
+typedef unsigned int uint;
+
 class Speedy
 {
 private:
     http::HttpServer server;
     http::Ipv4 ip;
+    node *n;
+    std::vector<http::request_cb_t> callbacks;
+    void store_index(int method, const std::string &path);
 public:
     Speedy(uv::UvLoop& loop, const http::Ipv4& ip);
-    void get(const std::string path, http::request_cb_t callback); 
+    void get(const std::string &path, http::request_cb_t callback);
+    void post(const std::string &path, http::request_cb_t callback);
+    void put(const std::string &path, http::request_cb_t callback);
+    void del(const std::string &path, http::request_cb_t callback);
     void listen();
-    ~Speedy();
 };
 
 }
diff --git a/speedy/speedy.inl b/speedy/speedy.inl
index 36ebefa58..b56d7cd60 100644
--- a/speedy/speedy.inl
+++ b/speedy/speedy.inl
@@ -2,31 +2,94 @@
 #define MEMGRAPH_SPEEDY_INL
 
 #include "speedy.hpp"
+#include <http_parser.h>
 
 namespace speedy
 {
 
-Speedy::Speedy(uv::UvLoop& loop, const http::Ipv4& ip) : server(loop), ip(ip)
+int r3_request_method(http::Method method)
 {
+    switch (method) {
+        case http::Method::GET: return METHOD_GET;
+        case http::Method::POST: return METHOD_POST;
+        case http::Method::PUT: return METHOD_PUT;
+        case http::Method::DELETE: return METHOD_DELETE;
+        case http::Method::HEAD: return METHOD_HEAD;
+    }
 }
 
-void Speedy::get(const std::string path, http::request_cb_t callback)
+// TODO: better implementation
+
+Speedy::Speedy(uv::UvLoop& loop, const http::Ipv4& ip) : server(loop), ip(ip)
 {
+    n = r3_tree_create(100);
+}
+
+void Speedy::store_index(int method, const std::string &path)
+{
+    void *ptr = malloc(sizeof(uint));
+    *((uint *)ptr) = callbacks.size() - 1;
+    r3_tree_insert_routel(n, method, path.c_str(), path.size(), ptr);
+}
+
+void Speedy::get(const std::string &path, http::request_cb_t callback)
+{
+    callbacks.push_back(callback);
+    store_index(METHOD_GET, path);
+
+    // TODO: something like this
+    // this solution doesn't work, currenlty I don't know why
+    // r3_tree_insert_pathl(n, path.c_str(), path.size(), &callbacks.back());
+}
+
+void Speedy::post(const std::string &path, http::request_cb_t callback)
+{
+    callbacks.push_back(callback);
+    store_index(METHOD_POST, path);
+}
+
+void Speedy::put(const std::string &path, http::request_cb_t callback)
+{
+    callbacks.push_back(callback);
+    store_index(METHOD_PUT, path);
+}
+
+void Speedy::del(const std::string &path, http::request_cb_t callback)
+{
+    callbacks.push_back(callback);
+    store_index(METHOD_DELETE, path);
 }
 
 void Speedy::listen()
 {
-    server.listen(ip, [](http::Request& req, http::Response& res) {
-        res.send(req.url);
+    char *errstr = NULL;
+    int err = r3_tree_compile(n, &errstr);
+    if (err) {
+        std::cout << "R3 compile error" << std::endl;
+    }
+
+    server.listen(ip, [this](http::Request& req, http::Response& res) {
+        auto url = req.url;
+        auto c_url = url.c_str();
+        match_entry *entry = match_entry_create(c_url);
+        entry->request_method = r3_request_method(req.method);
+        route *r = r3_tree_match_route(this->n, entry);
+        match_entry_free(entry);
+        if (r) {
+            int index = *((int *)r->data);
+            auto callback = this->callbacks[index];
+            callback(req, res);
+            // TODO: and something like this
+            // auto callback = *reinterpret_cast<http::request_cb_t*>(n->data);
+            // callback(req, res);
+        } else {
+            res.send("Not found");
+        }
     });
 
     std::cout << "Server is UP" << std::endl;
 }
 
-Speedy::~Speedy()
-{
-}
-
 }
 
 #endif
diff --git a/speedy/test.cpp b/speedy/test.cpp
index fc829001f..a0d07c2e8 100644
--- a/speedy/test.cpp
+++ b/speedy/test.cpp
@@ -2,14 +2,65 @@
 
 #include "speedy.hpp"
 
+const char *test_url_1 = "/test1";
+const char *test_url_2 = "/test2";
+const char *test_url_3 = "/test3";
+const char *test_response = "test";
+
+void test_get(const http::request_cb_t &&callback, speedy::Speedy &app) {
+    app.get(test_url_3, callback);
+}
+
+void test_post(const http::request_cb_t &&callback, speedy::Speedy &app) {
+    app.post(test_url_3, callback);
+}
+
+void test_put(const http::request_cb_t &&callback, speedy::Speedy &app) {
+    app.put(test_url_3, callback);
+}
+
+void test_delete(const http::request_cb_t &&callback, speedy::Speedy &app) {
+    app.del(test_url_3, callback);
+}
+
+auto test_callback = [](http::Request& req, http::Response& res) {
+    res.send(test_response);
+};
+
 int main(void)
 {
+    // speedy init
     uv::UvLoop loop;
     http::Ipv4 ip("0.0.0.0", 3400);
-
     speedy::Speedy app(loop, ip);
-    app.listen();
 
+    // GET methods
+    app.get(test_url_1, test_callback);
+    app.get(test_url_2, [](http::Request& req, http::Response& res) {
+        res.send(test_response);
+    });
+    test_get(test_callback, app);
+    // POST examples
+    app.post(test_url_1, test_callback);
+    app.post(test_url_2, [](http::Request& req, http::Response& res) {
+        res.send(test_response);
+    });
+    test_post(test_callback, app);
+    // PUT examples
+    app.put(test_url_1, test_callback);
+    app.put(test_url_2, [](http::Request& req, http::Response& res) {
+        res.send(test_response);
+    });
+    test_put(test_callback, app);
+    // DELETE examples
+    app.del(test_url_1, test_callback);
+    app.del(test_url_2, [](http::Request& req, http::Response& res) {
+        res.send(test_response);
+    });
+    test_delete(test_callback, app);
+
+    // app run
+    app.listen();
     loop.run(uv::UvLoop::Mode::Default);
 
     return 0;
diff --git a/speedy/test.py b/speedy/test.py
new file mode 100644
index 000000000..961684567
--- /dev/null
+++ b/speedy/test.py
@@ -0,0 +1,22 @@
+import requests
+
+endpoint = 'http://localhost:3400/test%s'
+methods = [('GET', requests.get), ('POST', requests.post), ('PUT', requests.put), ('DELETE', requests.delete)]
+
+print ''
+isAllFine = True
+for index in range(1, 4):
+    for name, method in methods:
+        url = endpoint % index
+        r = method(url)
+        if r.status_code == 200 and r.text == 'test':
+            print name, url, 'PASS'
+        else:
+            print name, url, 'FAIL'
+            isAllFine = False
+print ''
+if isAllFine:
+    print 'Great. All tests have passed :)'
+else:
+    print 'Fuckup. Something went wrong!'
+print ''