diff --git a/.travis.yml b/.travis.yml
index 0a110a9452..db5dd3dd8b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 language: rust
 rust:
-  - 1.3.0
+  - 1.6.0
   - stable
   - beta
   - nightly
diff --git a/Cargo.toml b/Cargo.toml
index 2160b44447..933b29a524 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,7 +18,7 @@ aho-corasick = "0.5.1"
 # For skipping along search text quickly when a leading byte is known.
 memchr = "0.1.9"
 # For managing regex caches quickly across multiple threads.
-mempool = "0.3.0"
+thread_local = "0.2.0"
 # For parsing regular expressions.
 regex-syntax = { path = "regex-syntax", version = "0.3.1" }
 # For compiling UTF-8 decoding into automata.
diff --git a/src/exec.rs b/src/exec.rs
index 51c2edf740..018bb1a7db 100644
--- a/src/exec.rs
+++ b/src/exec.rs
@@ -12,7 +12,7 @@ use std::cell::RefCell;
 use std::collections::HashMap;
 use std::sync::Arc;
 
-use mempool::Pool;
+use thread_local::CachedThreadLocal;
 use syntax::{Expr, ExprBuilder, Literals};
 
 use backtrack;
@@ -33,12 +33,11 @@ use set;
 /// In particular, this manages the various compiled forms of a single regular
 /// expression and the choice of which matching engine to use to execute a
 /// regular expression.
-#[derive(Debug)]
 pub struct Exec {
     /// All read only state.
     ro: Arc<ExecReadOnly>,
     /// Caches for the various matching engines.
-    cache: Pool<ProgramCache>,
+    cache: CachedThreadLocal<ProgramCache>,
 }
 
 /// ExecNoSync is like Exec, except it embeds a reference to a cache. This
@@ -204,8 +203,7 @@ impl ExecBuilder {
                 suffixes: LiteralSearcher::empty(),
                 match_type: MatchType::Nothing,
             });
-            let ro_ = ro.clone();
-            return Ok(Exec { ro: ro, cache: create_pool(ro_) });
+            return Ok(Exec { ro: ro, cache: CachedThreadLocal::new() });
         }
         let parsed = try!(Parsed::parse(&self.res, self.only_utf8));
         let mut nfa = try!(
@@ -245,8 +243,7 @@ impl ExecBuilder {
         // println!("MATCH TYPE for '{:?}': {:?}", ro.res, ro.match_type);
 
         let ro = Arc::new(ro);
-        let ro_ = ro.clone();
-        Ok(Exec { ro: ro, cache: create_pool(ro_) })
+        Ok(Exec { ro: ro, cache: CachedThreadLocal::new() })
     }
 }
 
@@ -703,9 +700,10 @@ impl Exec {
     /// Get a searcher that isn't Sync.
     #[inline(always)] // reduces constant overhead
     pub fn searcher(&self) -> ExecNoSync {
+        let create = || Box::new(RefCell::new(ProgramCacheInner::new(&self.ro)));
         ExecNoSync {
             ro: &self.ro, // a clone is too expensive here! (and not needed)
-            cache: self.cache.get(),
+            cache: self.cache.get_or(create),
         }
     }
 
@@ -759,7 +757,7 @@ impl Clone for Exec {
     fn clone(&self) -> Exec {
         Exec {
             ro: self.ro.clone(),
-            cache: create_pool(self.ro.clone()),
+            cache: CachedThreadLocal::new(),
         }
     }
 }
@@ -863,11 +861,6 @@ pub struct ProgramCacheInner {
     pub dfa_reverse: dfa::Cache,
 }
 
-/// Creates a fresh pool.
-fn create_pool(ro: Arc<ExecReadOnly>) -> Pool<ProgramCache> {
-    Pool::new(Box::new(move || RefCell::new(ProgramCacheInner::new(&ro))))
-}
-
 impl ProgramCacheInner {
     fn new(ro: &ExecReadOnly) -> Self {
         ProgramCacheInner {
diff --git a/src/lib.rs b/src/lib.rs
index dfc37451f6..61030ebe4d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -505,7 +505,7 @@
 
 extern crate aho_corasick;
 extern crate memchr;
-extern crate mempool;
+extern crate thread_local;
 #[cfg(test)] extern crate quickcheck;
 extern crate regex_syntax as syntax;
 extern crate utf8_ranges;