exception safety
diff --git a/theta/include/theta_update_sketch_base.hpp b/theta/include/theta_update_sketch_base.hpp
index eae7984..4be1040 100644
--- a/theta/include/theta_update_sketch_base.hpp
+++ b/theta/include/theta_update_sketch_base.hpp
@@ -53,6 +53,8 @@
   inline uint64_t hash_and_screen(const void* data, size_t length);
 
   inline std::pair<iterator, bool> find(uint64_t key) const;
+  static inline std::pair<iterator, bool> find(Entry* entries, uint8_t lg_size, uint64_t key);
+
 
   template<typename FwdEntry>
   inline void insert(iterator it, FwdEntry&& entry);
diff --git a/theta/include/theta_update_sketch_base_impl.hpp b/theta/include/theta_update_sketch_base_impl.hpp
index ce577e6..dce2ce9 100644
--- a/theta/include/theta_update_sketch_base_impl.hpp
+++ b/theta/include/theta_update_sketch_base_impl.hpp
@@ -136,18 +136,23 @@
 
 template<typename EN, typename EK, typename A>
 auto theta_update_sketch_base<EN, EK, A>::find(uint64_t key) const -> std::pair<iterator, bool> {
-  const size_t size = 1ULL << lg_cur_size_;
+  return find(entries_, lg_cur_size_, key);
+}
+
+template<typename EN, typename EK, typename A>
+auto theta_update_sketch_base<EN, EK, A>::find(EN* entries, uint8_t lg_size, uint64_t key) -> std::pair<iterator, bool> {
+  const size_t size = 1 << lg_size;
   const size_t mask = size - 1;
-  const uint32_t stride = get_stride(key, lg_cur_size_);
+  const uint32_t stride = get_stride(key, lg_size);
   uint32_t index = static_cast<uint32_t>(key) & mask;
   // search for duplicate or zero
   const uint32_t loop_index = index;
   do {
-    const uint64_t probe = EK()(entries_[index]);
+    const uint64_t probe = EK()(entries[index]);
     if (probe == 0) {
-      return std::pair<iterator, bool>(&entries_[index], false);
+      return std::pair<iterator, bool>(&entries[index], false);
     } else if (probe == key) {
-      return std::pair<iterator, bool>(&entries_[index], true);
+      return std::pair<iterator, bool>(&entries[index], true);
     }
     index = (index + stride) & mask;
   } while (index != loop_index);
@@ -193,22 +198,23 @@
 template<typename EN, typename EK, typename A>
 void theta_update_sketch_base<EN, EK, A>::resize() {
   const size_t old_size = 1ULL << lg_cur_size_;
-  const uint8_t lg_tgt_size = lg_nom_size_ + 1;
-  const uint8_t factor = std::max<uint8_t>(1, std::min<uint8_t>(static_cast<uint8_t>(rf_), static_cast<uint8_t>(lg_tgt_size - lg_cur_size_)));
-  lg_cur_size_ += factor;
-  const size_t new_size = 1ULL << lg_cur_size_;
-  EN* old_entries = entries_;
-  entries_ = allocator_.allocate(new_size);
-  for (size_t i = 0; i < new_size; ++i) EK()(entries_[i]) = 0;
-  num_entries_ = 0;
+  const uint8_t lg_new_size = std::min<uint8_t>(lg_cur_size_ + static_cast<uint8_t>(rf_), lg_nom_size_ + 1);
+  const size_t new_size = 1ULL << lg_new_size;
+  EN* new_entries = allocator_.allocate(new_size);
+  for (size_t i = 0; i < new_size; ++i) EK()(new_entries[i]) = 0;
   for (size_t i = 0; i < old_size; ++i) {
-    const uint64_t key = EK()(old_entries[i]);
+    const uint64_t key = EK()(entries_[i]);
     if (key != 0) {
-      insert(find(key).first, std::move(old_entries[i])); // consider a special insert with no comparison
-      old_entries[i].~EN();
+      // always finds an empty slot in a larger table
+      new (find(new_entries, lg_new_size, key).first) EN(std::move(entries_[i]));
     }
   }
-  allocator_.deallocate(old_entries, old_size);
+  std::swap(entries_, new_entries);
+  lg_cur_size_ = lg_new_size;
+  for (size_t i = 0; i < old_size; ++i) {
+    if (EK()(new_entries[i]) != 0) new_entries[i].~EN();
+  }
+  allocator_.deallocate(new_entries, old_size);
 }
 
 // assumes number of entries > nominal size