diff --git a/build/.gitignore b/build/.gitignore
index d6b7ef32c..051042cc0 100644
--- a/build/.gitignore
+++ b/build/.gitignore
@@ -1,2 +1,3 @@
-*
+/*
 !.gitignore
+!/compiled
diff --git a/build/compiled/.gitignore b/build/compiled/.gitignore
new file mode 100644
index 000000000..6a16f0329
--- /dev/null
+++ b/build/compiled/.gitignore
@@ -0,0 +1,3 @@
+/*
+!.gitignore
+!/cpu
diff --git a/build/compiled/cpu/.gitignore b/build/compiled/cpu/.gitignore
new file mode 100644
index 000000000..50ce2e0a4
--- /dev/null
+++ b/build/compiled/cpu/.gitignore
@@ -0,0 +1,3 @@
+/*
+!.gitignore
+!/hardcode
diff --git a/build/compiled/cpu/hardcode/9470552549410791677.cpp b/build/compiled/cpu/hardcode/9470552549410791677.cpp
new file mode 100644
index 000000000..036c84ad0
--- /dev/null
+++ b/build/compiled/cpu/hardcode/9470552549410791677.cpp
@@ -0,0 +1,149 @@
+#include <iostream>
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "query_engine/i_code_cpu.hpp"
+#include "storage/model/properties/all.hpp"
+
+using std::cout;
+using std::endl;
+
+// Dressipi astar query of 4 clicks.
+
+// BARRIER!
+namespace barrier
+{
+
+// using STREAM = std::ostream;
+using STREAM = RecordStream<::io::Socket>;
+
+constexpr size_t max_depth = 3;
+constexpr size_t limit = 10;
+
+class Node
+{
+public:
+    Node *parent = {nullptr};
+    VertexPropertyType<Double> tkey;
+    double cost;
+    int depth = {0};
+    VertexAccessor vacc;
+
+    Node(VertexAccessor vacc, double cost,
+         VertexPropertyType<Double> const &tkey)
+        : cost(cost), vacc(vacc), tkey(tkey)
+    {
+    }
+    Node(VertexAccessor vacc, double cost, Node *parent,
+         VertexPropertyType<Double> const &tkey)
+        : cost(cost), vacc(vacc), parent(parent), depth(parent->depth + 1),
+          tkey(tkey)
+    {
+    }
+
+    double sum_vertex_score()
+    {
+        auto now = this;
+        double sum = 0;
+        do {
+            sum += (now->vacc.at(tkey).get())->value();
+            now = now->parent;
+        } while (now != nullptr);
+        return sum;
+    }
+};
+
+bool vertex_filter_contained(DbAccessor &t, VertexAccessor &v, Node *before)
+{
+    if (v.fill()) {
+        bool found;
+        do {
+            found = false;
+            before = before->parent;
+            if (before == nullptr) {
+                return true;
+            }
+        } while (v.in_contains(before->vacc));
+    }
+    return false;
+}
+
+void astar(DbAccessor &t, code_args_t &args, STREAM &stream)
+{
+    VertexPropertyType<Double> tkey = t.vertex_property_key<Double>("score");
+
+    auto cmp = [](Node *left, Node *right) { return left->cost > right->cost; };
+    std::priority_queue<Node *, std::vector<Node *>, decltype(cmp)> queue(cmp);
+    std::vector<Node *> all_nodes;
+
+    auto start_vr = t.vertex_find(Id(args[0].as<Int64>().value()));
+    if (!start_vr.is_present()) {
+        stream.write_failure({{}});
+        return;
+    }
+
+    start_vr.get().fill();
+    Node *start = new Node(start_vr.take(), 0, tkey);
+    queue.push(start);
+    all_nodes.push_back(start);
+
+    int count = 0;
+    do {
+        auto now = queue.top();
+        queue.pop();
+
+        if (max_depth <= now->depth) {
+            // best.push_back(now);
+            count++;
+            if (count >= limit) {
+                break;
+            }
+            continue;
+        }
+
+        iter::for_all(now->vacc.out(), [&](auto edge) {
+            VertexAccessor va = edge.to();
+            if (vertex_filter_contained(t, va, now)) {
+                auto cost = 1 - va.at(tkey).get()->value();
+                Node *n = new Node(va, now->cost + cost, now, tkey);
+                queue.push(n);
+                all_nodes.push_back(n);
+            }
+        });
+    } while (!queue.empty());
+
+	stream.write_field("n");
+    stream.write_record();
+    stream.write_list_header(0);
+    stream.chunk();
+    stream.write_meta("r");
+
+    for (auto n : all_nodes) {
+        delete n;
+    }
+}
+
+class CodeCPU : public ICodeCPU<STREAM>
+{
+public:
+    bool run(Db &db, code_args_t &args, STREAM &stream) override
+    {
+        DbAccessor t(db);
+
+        astar(t, args, stream);
+
+        return t.commit();
+    }
+
+    ~CodeCPU() {}
+};
+}
+
+extern "C" ICodeCPU<barrier::STREAM> *produce()
+{
+    // BARRIER!
+    return new barrier::CodeCPU();
+}
+
+extern "C" void destruct(ICodeCPU<barrier::STREAM> *p) { delete p; }
diff --git a/include/barrier/barrier.hpp b/include/barrier/barrier.hpp
index 2d5edf002..0d52ef6ca 100644
--- a/include/barrier/barrier.hpp
+++ b/include/barrier/barrier.hpp
@@ -493,6 +493,7 @@ public:
     void write_list_header(size_t size);
     void write_record();
     void write_meta(const std::string &type);
+    void write_failure(const std::map<std::string, std::string> &data);
     void send();
     void chunk();
 };
diff --git a/include/barrier/common.hpp b/include/barrier/common.hpp
index ff89a9b1e..ed3f1a054 100644
--- a/include/barrier/common.hpp
+++ b/include/barrier/common.hpp
@@ -4,6 +4,7 @@
 #include <type_traits>
 #include <utility>
 #include <vector>
+#include <map>
 
 // THis shoul be the only place to include code from memgraph other than
 // barrier.cpp
diff --git a/include/query_engine/code_generator/clause_action.hpp b/include/query_engine/code_generator/clause_action.hpp
index b3c997651..6681259b5 100644
--- a/include/query_engine/code_generator/clause_action.hpp
+++ b/include/query_engine/code_generator/clause_action.hpp
@@ -16,5 +16,6 @@ enum class ClauseAction : uint32_t
     ReturnNode,
     ReturnRelationship,
     ReturnPack,
-    ReturnProjection
+    ReturnProjection,
+    ReturnCount
 };
diff --git a/include/query_engine/code_generator/handlers/return.hpp b/include/query_engine/code_generator/handlers/return.hpp
index 6a77c9615..9d16cb550 100644
--- a/include/query_engine/code_generator/handlers/return.hpp
+++ b/include/query_engine/code_generator/handlers/return.hpp
@@ -69,5 +69,18 @@ auto return_query_action =
         }
     }
 
+    // return functions
+    for (auto const &kv : action_data.actions)
+    {
+        auto name = kv.first;
+        if (kv.second == ClauseAction::ReturnCount)
+        {
+            if (cypher_data.source(name) == EntitySource::MainStorage)
+            {
+                code += code_line(code::count, name);
+            }
+        }
+    }
+
     return code;
 };
diff --git a/include/query_engine/program_loader.hpp b/include/query_engine/program_loader.hpp
index aef72a4e3..ae7255ff2 100644
--- a/include/query_engine/program_loader.hpp
+++ b/include/query_engine/program_loader.hpp
@@ -12,6 +12,7 @@
 #include "query_engine/query_stripper.hpp"
 #include "utils/hashing/fnv.hpp"
 #include "logging/default.hpp"
+#include "utils/file.hpp"
 
 using std::string;
 
@@ -46,16 +47,32 @@ public:
             return query_program_t(code, std::move(stripped));
         }
 
-        // code has to be generated, compiled and loaded
-        //  TODO load output path from config
         auto base_path = CONFIG(config::COMPILE_CPU_PATH);
         auto path_cpp = base_path + hash_string + ".cpp";
+        auto hard_code_cpp = base_path + "hardcode/" + hash_string + ".cpp";
         auto stripped_space = stripper.strip_space(query);
-        code_generator.generate_cpp(stripped_space.query, stripped.hash,
-                                    path_cpp);
 
+        // cpp files in the hardcode folder have bigger priority then
+        // other cpp files
+        if (!utils::fexists(hard_code_cpp))
+        {
+            code_generator.generate_cpp(stripped_space.query, stripped.hash,
+                                        path_cpp);
+        }
+
+        // compile the code
         auto path_so = base_path + hash_string + ".so";
-        code_compiler.compile(path_cpp, path_so);
+
+        // hardcoded queries are compiled to the same folder as generated
+        // queries (all .so files are in the same folder)
+        if (utils::fexists(hard_code_cpp))
+        {
+            code_compiler.compile(hard_code_cpp, path_so);
+        }
+        else
+        {
+            code_compiler.compile(path_cpp, path_so);
+        }
 
         // loads dynamic lib and store it
         auto code_lib = load_code_lib(path_so);
diff --git a/include/query_engine/traverser/code.hpp b/include/query_engine/traverser/code.hpp
index 9bd035fae..e274efe66 100644
--- a/include/query_engine/traverser/code.hpp
+++ b/include/query_engine/traverser/code.hpp
@@ -105,6 +105,18 @@ const std::string find_and_write_edges_by_type =
     "        }});\n"
     "        stream.write_meta(\"rw\");\n";
 
+// TODO: vertices and edges
+const std::string count =
+    "size_t count = 0;\n"
+    "        t.vertex_access().fill().for_all(\n"
+    "            [&](auto vertex) {{ ++count; }});\n"
+    "        stream.write_field(\"count({0})\");\n"
+    "        stream.write_record();\n"
+    "        stream.write_list_header(1);\n"
+    "        stream.write(Int64(count));\n"
+    "        stream.chunk();\n"
+    "        stream.write_meta(\"r\");\n";
+
 const std::string return_true = "return true;";
 
 const std::string todo = "// TODO: {}";
diff --git a/include/query_engine/traverser/cpp_traverser.hpp b/include/query_engine/traverser/cpp_traverser.hpp
index 15e2bbfef..7dc69ebf3 100644
--- a/include/query_engine/traverser/cpp_traverser.hpp
+++ b/include/query_engine/traverser/cpp_traverser.hpp
@@ -519,4 +519,15 @@ public:
 
         code += generator.generate();
     }
+
+    void visit(ast::CountFunction& ast_count) override
+    {
+        auto &action_data = generator.action_data();
+        auto &cypher_data = generator.cypher_data();
+
+        if (state == CypherState::Return)
+        {
+            action_data.actions[ast_count.argument] = ClauseAction::ReturnCount;
+        }
+    }
 };
diff --git a/include/utils/align.hpp b/include/utils/align.hpp
new file mode 100644
index 000000000..b900b03ac
--- /dev/null
+++ b/include/utils/align.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+// FROM: A Malloc Tutorial, Marwan Burelle, 2009
+
+// align address x to 4 bytes
+#define align_4(x) (((((x) - 1)>>2)<<2)+4)
+
+// align address x to 8 bytes
+#define align_8(x) (((((x) - 1)>>3)<<3)+8)
diff --git a/include/utils/file.hpp b/include/utils/file.hpp
new file mode 100644
index 000000000..f07edd033
--- /dev/null
+++ b/include/utils/file.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <fstream>
+
+namespace utils
+{
+
+inline bool fexists(const char *filename)
+{
+  std::ifstream ifile(filename);
+  return (bool)ifile;
+}
+
+inline bool fexists(const std::string& filename)
+{
+  std::ifstream ifile(filename.c_str());
+  return (bool)ifile;
+}
+
+}
diff --git a/poc/queries/astar.cpp b/poc/queries/astar.cpp
index 6f1243217..5133e80f2 100644
--- a/poc/queries/astar.cpp
+++ b/poc/queries/astar.cpp
@@ -15,7 +15,8 @@ using std::endl;
 namespace barrier
 {
 
-using STREAM = std::ostream; // RecordStream<::io::Socket>;
+// using STREAM = std::ostream;
+using STREAM = RecordStream<::io::Socket>;
 
 constexpr size_t max_depth = 3;
 constexpr size_t limit = 10;
@@ -78,7 +79,7 @@ void astar(DbAccessor &t, code_args_t &args, STREAM &stream)
 
     auto start_vr = t.vertex_find(Id(args[0].as<Int64>().value()));
     if (!start_vr.is_present()) {
-        // stream.write_failure({{}});
+        stream.write_failure({{}});
         return;
     }
 
@@ -93,7 +94,7 @@ void astar(DbAccessor &t, code_args_t &args, STREAM &stream)
         queue.pop();
 
         if (max_depth <= now->depth) {
-            // stream.write_success_empty();
+            stream.write_success_empty();
             // best.push_back(now);
             count++;
             if (count >= limit) {
diff --git a/src/barrier/barrier.cpp b/src/barrier/barrier.cpp
index 4a9ab5320..659119a3f 100644
--- a/src/barrier/barrier.cpp
+++ b/src/barrier/barrier.cpp
@@ -674,6 +674,12 @@ void RecordStream<Stream>::write_meta(const std::string &type)
     HALF_CALL(write_meta(type));
 }
 
+template <class Stream>
+void RecordStream<Stream>::write_failure(const std::map<std::string, std::string> &data)
+{
+    HALF_CALL(write_failure(data));
+}
+
 template <class Stream>
 void RecordStream<Stream>::send()
 {
diff --git a/src/cypher/ast/ast.hpp b/src/cypher/ast/ast.hpp
index 29e2e9408..04b356ee6 100644
--- a/src/cypher/ast/ast.hpp
+++ b/src/cypher/ast/ast.hpp
@@ -19,3 +19,4 @@
 #include "set.hpp"
 #include "expr.hpp"
 #include "with.hpp"
+#include "functions.hpp"
diff --git a/src/cypher/ast/ast_visitor.hpp b/src/cypher/ast/ast_visitor.hpp
index ba53cc3e4..76a0cf331 100644
--- a/src/cypher/ast/ast_visitor.hpp
+++ b/src/cypher/ast/ast_visitor.hpp
@@ -36,6 +36,9 @@ struct Star;
 struct Slash;
 struct Rem;
 
+// functions
+struct CountFunction;
+
 struct RelationshipSpecs;
 struct RelationshipTypeList;
 struct Relationship;
@@ -83,6 +86,7 @@ struct AstVisitor
           PatternList, Match, ReadQuery, Start, Where, WriteQuery, Create,
           Return, Distinct, Delete, DeleteQuery, UpdateQuery, Set, SetKey,
           ReadWriteQuery, IdentifierList, WithList, WithClause, WithQuery, Long,
+          CountFunction,
           InternalIdExpr, SetValue, SetElement, SetList>
 {
 };
diff --git a/src/cypher/ast/expr.hpp b/src/cypher/ast/expr.hpp
index 0e80100a0..f85e902ca 100644
--- a/src/cypher/ast/expr.hpp
+++ b/src/cypher/ast/expr.hpp
@@ -24,6 +24,16 @@ struct LeafExpr : public ValueExpr<Derived>
     T value;
 };
 
+// T is argument type
+template <class T, class Derived>
+struct FunctionExpr : public ValueExpr<Derived>
+{
+    FunctionExpr(const std::string& name, T argument) : name(name), argument(argument) {}
+    
+    std::string name;
+    T argument;
+};
+
 template <class Derived>
 struct BinaryExpr : public ValueExpr<Derived>
 {
@@ -43,4 +53,5 @@ struct PatternExpr : public Expr
 
     Pattern *pattern;
 };
+
 }
diff --git a/src/cypher/ast/functions.hpp b/src/cypher/ast/functions.hpp
new file mode 100644
index 000000000..53d2bb7b8
--- /dev/null
+++ b/src/cypher/ast/functions.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "expr.hpp"
+
+namespace ast
+{
+
+struct CountFunction : public FunctionExpr<std::string, CountFunction>
+{
+    CountFunction(const std::string &argument) : FunctionExpr("count", argument)
+    {
+    }
+};
+}
diff --git a/src/cypher/cypher.y b/src/cypher/cypher.y
index bfc9891d4..bd65e6a2a 100644
--- a/src/cypher/cypher.y
+++ b/src/cypher/cypher.y
@@ -495,6 +495,12 @@ pattern_expr(E) ::= pattern(P). {
     E = ast->create<ast::PatternExpr>(P);
 }
 
+%type function_expr {ast::Expr*}
+
+function_expr(E) ::= COUNT LP IDN(A) RP. {
+    E = ast->create<ast::CountFunction>(A->value);
+}
+
 %type expr {ast::Expr*}
 
 expr(E) ::= value_expr(V). {
@@ -505,6 +511,10 @@ expr(E) ::= pattern_expr(P). {
     E = P;
 }
 
+expr(E) ::= function_expr(F). {
+    E = F;
+}
+
 //%type alias {ast::Alias*}
 //
 //alias(A) ::= IDN(X) AS IDN(Y). {
diff --git a/src/cypher/debug/tree_print.hpp b/src/cypher/debug/tree_print.hpp
index 1ea4658d6..d16fb30d9 100644
--- a/src/cypher/debug/tree_print.hpp
+++ b/src/cypher/debug/tree_print.hpp
@@ -294,6 +294,12 @@ public:
         Traverser::visit(rem);
     }
 
+    void visit(ast::CountFunction& count) override
+    {
+        auto entry = printer.advance("Count ");
+        entry << count.name << "(" << count.argument << ")";
+    }
+
     void visit(ast::PropertyList& prop_list) override
     {
         auto entry = printer.advance("Property List");
diff --git a/src/cypher/tokenizer/cypher_lexer.hpp b/src/cypher/tokenizer/cypher_lexer.hpp
index 13c1b1758..3d708b48a 100644
--- a/src/cypher/tokenizer/cypher_lexer.hpp
+++ b/src/cypher/tokenizer/cypher_lexer.hpp
@@ -58,6 +58,9 @@ public:
         rule("(?i:AND)", TK_AND);
         rule("(?i:OR)", TK_OR);
 
+        // functions
+        rule("(?i:COUNT)", TK_COUNT);
+
         // string literal TODO single quote escape
         rule("'(.*?)'", TK_STR);
 
diff --git a/src/cypher/visitor/traverser.hpp b/src/cypher/visitor/traverser.hpp
index 87d68ff77..66c5e9090 100644
--- a/src/cypher/visitor/traverser.hpp
+++ b/src/cypher/visitor/traverser.hpp
@@ -154,6 +154,10 @@ public:
         accept(rem.right);
     }
 
+    void visit(ast::CountFunction& count) override
+    {
+    }
+
     void visit(ast::PropertyList& prop_list) override
     {
         accept(prop_list.value);