reuse GRV within an http request
diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index 636aad9..0e828f6 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -153,6 +153,7 @@
     mochiweb_http:stop(?MODULE).
 
 handle_request(MochiReq0) ->
+    fabric2_fdb:init_grv_cache(),
     erlang:put(?REWRITE_COUNT, 0),
     MochiReq = couch_httpd_vhost:dispatch_host(MochiReq0),
     handle_request_int(MochiReq).
diff --git a/src/fabric/include/fabric2.hrl b/src/fabric/include/fabric2.hrl
index ebbb7c7..62ad9b9 100644
--- a/src/fabric/include/fabric2.hrl
+++ b/src/fabric/include/fabric2.hrl
@@ -76,6 +76,8 @@
 -define(PDICT_TX_ID_KEY, '$fabric_tx_id').
 -define(PDICT_TX_RES_KEY, '$fabric_tx_result').
 -define(PDICT_FOLD_ACC_STATE, '$fabric_fold_acc_state').
+-define(PDICT_GRV_CACHE_ENABLED, '$fabric_grv_cache_enabled').
+-define(PDICT_GRV_CACHE, '$fabric_grv_cache').
 
 % Let's keep these in ascending order
 -define(TRANSACTION_TOO_OLD, 1007).
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index 1690f2f..5394f27 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -19,6 +19,7 @@
     transactional/2,
 
     with_snapshot/2,
+    init_grv_cache/0,
 
     create/2,
     open/2,
@@ -165,6 +166,43 @@
     end).
 
 
+init_grv_cache() ->
+    clear_grv_cache(),
+    enable_grv_cache().
+
+
+enable_grv_cache() ->
+    put(?PDICT_GRV_CACHE_ENABLED, true).
+
+
+clear_grv_cache() ->
+    erase(?PDICT_GRV_CACHE).
+
+
+get_grv_cache() ->
+    get(?PDICT_GRV_CACHE).
+
+
+maybe_cache_grv(Tx) ->
+    case get(?PDICT_GRV_CACHE_ENABLED) of
+        undefined ->
+            ok;
+        true ->
+            GRV = erlfdb:wait(erlfdb:get_read_version(Tx)),
+            put(?PDICT_GRV_CACHE, GRV)
+    end.
+
+
+apply_then_clear_grv_cache(Tx) ->
+    case get_grv_cache() of
+        undefined ->
+            ok;
+        GRV ->
+            erlfdb:set_read_version(Tx, GRV),
+            clear_grv_cache()
+    end.
+
+
 do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) ->
     Db = get_db_handle(),
     try
@@ -557,6 +595,7 @@
             Future1 = get_info_future(Tx, Future#info_future.db_prefix),
             get_info_wait(Future1#info_future{retries = Retries + 1});
         error:{erlfdb_error, ?TRANSACTION_TOO_OLD} ->
+            clear_grv_cache(),
             ok = erlfdb:reset(Tx),
             Future1 = get_info_future(Tx, Future#info_future.db_prefix),
             get_info_wait(Future1#info_future{retries = Retries + 1})
@@ -1856,6 +1895,7 @@
 restart_fold(Tx, #fold_acc{} = Acc) ->
     erase(?PDICT_CHECKED_MD_IS_CURRENT),
 
+    clear_grv_cache(),
     ok = erlfdb:reset(Tx),
 
     case {erase(?PDICT_FOLD_ACC_STATE), Acc#fold_acc.retries} of
@@ -1957,9 +1997,11 @@
 execute_transaction(Tx, Fun, LayerPrefix) ->
     put(?PDICT_CHECKED_MD_IS_CURRENT, false),
     put(?PDICT_CHECKED_DB_IS_CURRENT, false),
+    apply_then_clear_grv_cache(Tx),
     Result = Fun(Tx),
     case erlfdb:is_read_only(Tx) of
         true ->
+            maybe_cache_grv(Tx),
             ok;
         false ->
             erlfdb:set(Tx, get_transaction_id(Tx, LayerPrefix), <<>>),