diff --git a/README.md b/README.md
index 45e58e1b47a03e3baedf5588d130b5c9d994ff15..2e50a5dcf2fdd5eec60c84fc0a98a226aaf135dd 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,157 @@
-consul_proxy
+Consul Proxy
 ============
 
-An OTP application
+A service router and load balancer that uses Consul for configuration and service lookups.
 
-Build
------
+Building
+--------
 
 ```bash
 rebar3 compile
 ```
 
-Testing
+Running
 -------
 
 ```bash
-while true ; do  echo -e "HTTP/1.1 200 OK\r\nConnection:close\r\n\r\n1:$(date)" | nc -l 8081  ; done
-while true ; do  echo -e "HTTP/1.1 200 OK\r\nConnection:close\r\n\r\n2:$(date)" | nc -l 8082  ; done
+docker run --name consul_proxy --net=host -d \
+  -e CONSUL_PROXY_HTTP_PORT="80" \
+  -e CONSUL_PROXY_CONSUL_URLS="\"http://localhost:8500\"" \
+  -p 80:80 \
+  -p 8081:8081 \
+  -p 8082:8082 \
+  -p 8083:8083 \
+  erlangninja/consul_proxy
 ```
 
+Configuration
+-------------
 
-Running
--------
+### Domains
 
-```bash
-docker run --name consul_proxy -d --net=host -e CONSUL_PROXY_CONSUL_URL="\"http://10.1.4.80:8500\"" -p 80:8080 ehedenst/consul_proxy:arm
+Path is `consul_proxy/domains/[DOMAIN]`
+
+#### Services
+
+```javascript
+{
+  "ServiceName" : "...",
+  "ServiceID" : "...",
+  "ServiceTags" : "..."
+}
 ```
 
-Todo
-----
+#### Nodes
 
-- Allow explicit setting of upstream/downstream headers
+```javascript
+{
+  "ServiceNodes" : [
+      "ServiceHost" : "...",
+      "ServiceAddress" : "...",
+      "ServicePort" : "..."
+  ]
+}
+```
 
+#### Resolver
 
-Domain descriptor
------------------
+```javascript
+{
+  "ServiceResolver" : "..."
+}
+```
 
+#### Headers
+
+```javascript
 {
-  "ServiceName" : "test", (String)
-  "ServiceID" : "fast", (Regexp)
-  "ServiceTags" : "fast" (Regexp)
-}
\ No newline at end of file
+  "Headers" : {
+    "Upstream" : [],
+    "Downstream" : []
+  }
+}
+```
+
+### Scripts
+
+Path is `consul_proxy/scripts/[NAME]`
+
+Properies passed to the script are a combination of the domain configuration and the following request propeties. 
+
+```erlang
+{request, [
+    {method, "..."},
+    {domain, "..."},
+    {port, "..."},
+    {path, "..."},
+    {query, []},
+    {headers, []},
+    {cookies, []},
+    {meta, [
+        {request_id, "..."},
+        {initial_host, "..."},
+        {host_capture, "..."}
+    ]}
+]}.
+```
+
+#### Erlang
+
+When the properties are passed to an Erlang script the properties are bound as a proplist to the variable `Props`. The script must return a proplist that contains the domain configuration.
+
+```erlang
+Request = proplists:get_value(request, Props, []),
+Meta = proplists:get_value(meta, Request, []),
+Capture = proplists:get_value(host_capture, Meta, []),
+ServiceName = proplists:get_value(<<"service">>, Capture),
+[{<<"ServiceName">>, ServiceName}].
+```
+
+#### Lua
+
+When the properties are passed to a Lua script the properties are bound as a table to the variable`props`. The script must return a table that contains the domain configuration.
+
+```lua
+return {ServiceName = props.request.meta.host_capture.service};
+```
+
+### Watchers
+
+Path is `consul_proxy/watchers/(kv | nodes | services)`
+
+### Hijackers
+
+Path is `consul_proxy/hijackers`
+
+```javascript
+[
+  {
+    "username" : "...",
+    "password" : "...",
+    "domains" : [
+      "...."
+    ]
+  }
+]
+```
+
+Middlewares
+-----------
+
+### Alias
+
+### Auth
+
+### Redirect
+
+### Rewrite
+
+### ACME
+
+### Hijack
+
+Load Balancing
+--------------
+
+Logging
+-------
diff --git a/apps/consul_proxy/src/consul_proxy_router.erl b/apps/consul_proxy/src/consul_proxy_router.erl
index 30e07e80c135489651ed526148289ee9db3d7300..6ce1bba92c64b6986fd40e505a1382a7d4a4cf42 100644
--- a/apps/consul_proxy/src/consul_proxy_router.erl
+++ b/apps/consul_proxy/src/consul_proxy_router.erl
@@ -91,19 +91,14 @@ lookup_services(Domain, Upstream, State) ->
         undefined ->
             case consul_proxy_utils:get_and_decode(<<"consul_proxy/domains/", Domain/binary>>) of
                 {ok, Properties} ->
-                    {Capture, Upstream1} = cowboyku_req:meta(host_capture, Upstream, []),
-                    InterpolatedProperties = consul_proxy_utils:string_interpolate(Properties, Capture, [<<"Rewrite">>]),
-                    ServiceName = proplists:get_value(<<"ServiceName">>, InterpolatedProperties),
-                    ServiceIDRE = proplists:get_value(<<"ServiceID">>, InterpolatedProperties, <<".*">>),
-                    ServiceTagsRE = proplists:get_value(<<"ServiceTags">>, InterpolatedProperties, <<".*">>),
-                    case lookup_services(Domain, Upstream1, InterpolatedProperties, {ServiceName, ServiceIDRE, ServiceTagsRE}, true) of
+                    case lookup_services(Domain, Upstream, Properties, true) of
                         {ok, Services, true} ->
                             consul_proxy_utils:cache_add(<<"services:", Domain/binary>>, {ok, Services}),
-                            {ok, Services, Upstream1, State};
+                            {ok, Services, Upstream, State};
                         {ok, Services, false} ->
-                            {ok, Services, Upstream1, State};
+                            {ok, Services, Upstream, State};
                         {error, Reason} ->
-                            {error, Reason, Upstream1, State}
+                            {error, Reason, Upstream, State}
                     end;
                 {error, Reason} ->
                     {error, Reason, Upstream, State}
@@ -112,6 +107,14 @@ lookup_services(Domain, Upstream, State) ->
             {ok, Services, Upstream, State}
     end.
 
+lookup_services(Domain, Upstream, Properties, CacheFlag) ->
+    {Capture, _} = cowboyku_req:meta(host_capture, Upstream, []),
+    InterpolatedProperties = consul_proxy_utils:string_interpolate(Properties, Capture, [<<"Rewrite">>]),
+    ServiceName = proplists:get_value(<<"ServiceName">>, InterpolatedProperties),
+    ServiceIDRE = proplists:get_value(<<"ServiceID">>, InterpolatedProperties, <<".*">>),
+    ServiceTagsRE = proplists:get_value(<<"ServiceTags">>, InterpolatedProperties, <<".*">>),
+    lookup_services(Domain, Upstream, InterpolatedProperties, {ServiceName, ServiceIDRE, ServiceTagsRE}, CacheFlag).
+
 lookup_services(Domain, Upstream, Properties, {undefined, _ServiceIDRE, _ServiceTagsRE}, CacheFlag) ->
     lookup_nodes(Domain, Upstream, Properties, proplists:get_value(<<"ServiceNodes">>, Properties), CacheFlag);
 lookup_services(_Domain, _Upstream, _Properties, {ServiceName, ServiceIDRE, ServiceTagsRE}, CacheFlag) ->
@@ -153,28 +156,9 @@ lookup_nodes(Domain, _Upstream, _Properties, Nodes, CacheFlag) ->
 lookup_resolver(_Domain, _Upstream, _Properties, undefined, _CacheFlag) ->
     {error, route_lookup_failed};
 lookup_resolver(Domain, Upstream, Properties, ServiceResolver, _CacheFlag) ->
-    case consul_proxy_utils:eval_script(ServiceResolver, build_script_vars(Upstream)) of
-        {ok, ServiceName} when is_binary(ServiceName) ->
-            lookup_services(Domain, Upstream, Properties, {ServiceName, <<".*">>, <<".*">>}, false);
-        {ok, [ServiceName]} when is_binary(ServiceName) ->
-            lookup_services(Domain, Upstream, Properties, {ServiceName, <<".*">>, <<".*">>}, false);
-        {ok, {ServiceName, ServiceID}} when is_binary(ServiceName), is_binary(ServiceID) ->
-            lookup_services(Domain, Upstream, Properties, {ServiceName, ServiceID, <<".*">>}, false);
-        {ok, {ServiceName, ServiceID, ServiceTags}} when is_binary(ServiceName), is_binary(ServiceID), is_binary(ServiceTags) ->
-            lookup_services(Domain, Upstream, Properties, {ServiceName, ServiceID, ServiceTags}, false);
-        {ok, {Host, Port}} when is_binary(Host), is_integer(Port) ->
-            lookup_nodes(Domain, Upstream, Properties, [[{<<"ServiceHost">>, Host}, {<<"ServicePort">>, Port}]], false);
-        {ok, Values} when is_list(Values) ->
-            Nodes = lists:foldl(
-                fun({Host, Port}, AccIn) when is_binary(Host), is_integer(Port) ->
-                    [[{<<"ServiceHost">>, Host}, {<<"ServicePort">>, Port}] | AccIn];
-                    (_, AccIn) ->
-                        AccIn
-                end, [], Values),
-            lookup_nodes(Domain, Upstream, Properties, Nodes, false);
-        {ok, Value} ->
-            lager:error("Can't convert value into nodes: ~p", [Value]),
-            {error, route_lookup_failed};
+    case consul_proxy_utils:eval_script(ServiceResolver, build_script_vars(Properties, Upstream)) of
+        {ok, Result} ->
+            lookup_services(Domain, Upstream, Result, false);
         {error, Reason} ->
             lager:error("Failed to evaluate '~s': ~p", [ServiceResolver, Reason]),
             {error, route_lookup_failed}
@@ -217,8 +201,8 @@ matches(Subject, RE) ->
             false
     end.
 
-build_script_vars(Req) ->
-    [
+build_script_vars(Props, Req) ->
+    Props ++ [
         {request, [
             {method, element(1, cowboyku_req:method(Req))},
             {domain, element(1, cowboyku_req:host(Req))},
@@ -233,4 +217,4 @@ build_script_vars(Req) ->
                 {host_capture, element(1, cowboyku_req:meta(host_capture, Req, []))}
             ]}
         ]}
-    ].
\ No newline at end of file
+    ].
diff --git a/apps/consul_proxy/src/consul_proxy_utils.erl b/apps/consul_proxy/src/consul_proxy_utils.erl
index 2faae062556226bca16866faf89f149e61775c5c..cb0dddda9faf8f5377aeca224e20c46cdc7bba20 100644
--- a/apps/consul_proxy/src/consul_proxy_utils.erl
+++ b/apps/consul_proxy/src/consul_proxy_utils.erl
@@ -205,15 +205,38 @@ eval_script(Name, Vars, <<".erl">>) ->
             end
     end;
 eval_script(Name, Vars, <<".lua">>) ->
-    case consul_client:get(<<"consul_proxy/scripts/", Name/binary>>) of
-        {error, Reason} ->
-            {error, Reason};
-        {ok, Binary} ->
+    Key = <<"lua_script:", Name/binary>>,
+    Parsed = case cache_get(Key) of
+                 undefined ->
+                     case consul_client:get(<<"consul_proxy/scripts/", Name/binary>>) of
+                         {error, Reason} ->
+                             {error, Reason};
+                         {ok, Binary} ->
+                             case luerl:load(Binary) of
+                                 {error, Reason} ->
+                                     {error, Reason};
+                                 {ok, Chunk, InitialState} ->
+                                     cache_add(Key, {Chunk, InitialState}),
+                                     {ok, Chunk, InitialState}
+                             end
+                     end;
+                 {Chunk, InitialState} ->
+                     {ok, Chunk, InitialState}
+             end,
+    case Parsed of
+        {error, Reason1} ->
+            {error, Reason1};
+        {ok, Chunk1, InitialState1} ->
             State = lists:foldl(
                 fun({Path, Value}, AccIn) ->
                     luerl:set_table(Path, Value, AccIn)
-                end, luerl:init(), vars_to_table([props], Vars)),
-            luerl:eval(Binary, State)
+                end, InitialState1, vars_to_table([props], Vars)),
+            case luerl:eval(Chunk1, State) of
+                {ok, [Result]} ->
+                    {ok, Result};
+                Error ->
+                    Error
+            end
     end;
 eval_script(Name, _Vars, _Suffix) ->
     {error, {unknown_language, Name}}.