diff --git a/concurrent-hashtable.cabal b/concurrent-hashtable.cabal
--- a/concurrent-hashtable.cabal
+++ b/concurrent-hashtable.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: dfbcbe83f4c3c52e2cf5b9e2db5e3898ada41cfbaf1f37a912b4cdd634a4bc05
+-- hash: cd9377375669850e36b4505949d445efc12cf57a2c9bb8ea352987259c507369
 
 name:           concurrent-hashtable
-version:        0.1.2
+version:        0.1.3
 synopsis:       Thread-safe hash tables for multi-cores!
 description:    Please see the README on GitHub at <https://github.com/pwrobinson/concurrent-hashtable#readme>
 category:       Concurrency
@@ -39,7 +39,6 @@
       async >=2.2.2 && <3
     , atomic-primops >=0.8.3 && <2
     , base >=4.7 && <5
-    , containers >=0.6.0.1 && <1
     , hashable >=1.2.7.0 && <2
     , random >=1.1 && <2
     , stm >=2.4.5.1 && <3
diff --git a/src/Data/HashTable.hs b/src/Data/HashTable.hs
--- a/src/Data/HashTable.hs
+++ b/src/Data/HashTable.hs
@@ -9,12 +9,29 @@
 -- Portability :  non-portable (requires concurrency, stm)
 --
 -- You can find benchmarks and more information about the internals of this package here:  <https://lowerbound.io/blog/2019-10-24_concurrent_hash_table_performance.html>
+--
+--
+-- Example usage:
+--
+-- >> ht <- newWithDefaults 2     -- creates hash table of initial size 4
+-- >> insert ht 1 "hello"         -- adds key-value pair (1,"hello")
+-- >> insert ht 2 "world"         -- adds key-value pair (2,"world")
+-- >> atomically $ readAssocs ht  -- convert to a key-value list
+-- > [(1,"hello"),(2,"world")]
+-- >> readSizeIO ht               -- returns 4
+-- >> insert ht 3 "!"             -- adds key-value pair (3,"!") and triggers a resize as the load fraction is ≥ 0.75
+-- >> readSizeIO ht               -- returns 8
+-- >> atomically $ readAssocs ht  -- convert to a key-value list
+-- > [(1,"hello"),(3,"!"),(2,"world")]
+--
+-- List of atomic operations:
+-- /insert/, /insertIfNotExists/, /lookup/, /delete/, /getAssocs/, /resize/
+--
 ----------------------------------------------------------------------
 
 module Data.HashTable(
         HashTable,
         Chain,
-        _itemsTV,
         new,
         newWithDefaults,
         mkDefaultConfig,
@@ -23,7 +40,9 @@
         insert,
         insertIfNotExists,
         delete,
-        getAssocs
+        readAssocs,
+        readSizeIO,
+        readSize
     )
 where
 import Data.HashTable.Internal
diff --git a/src/Data/HashTable/Internal.hs b/src/Data/HashTable/Internal.hs
--- a/src/Data/HashTable/Internal.hs
+++ b/src/Data/HashTable/Internal.hs
@@ -11,7 +11,7 @@
 -- You can find benchmarks and more information about the internals of this package here:  <https://lowerbound.io/blog/2019-10-24_concurrent_hash_table_performance.html>
 --
 -- List of atomic operations:
--- /insert/, /insertIfNotExists/, /lookup/, /delete/, /getAssocs/, /resize/
+-- /insert/, /insertIfNotExists/, /lookup/, /delete/, /readAssocs/, /resize/
 ----------------------------------------------------------------------
 {-# LANGUAGE MultiParamTypeClasses, ScopedTypeVariables #-}
 module Data.HashTable.Internal
@@ -38,7 +38,7 @@
 
 -- | Used for chain-hashing.
 data Chain k v = Chain
-    { _itemsTV           :: TVar [(k,v)]   -- ^ stores the
+    { _itemsTV           :: TVar [(k,v)]   -- ^ stores the items for this index
     , _migrationStatusTV :: TVar MigrationStatus -- ^ used internally for resizing
     }
     deriving (Eq)
@@ -104,9 +104,12 @@
 {-# INLINABLE readSizeIO #-}
 readSizeIO :: HashTable k v -> IO Int
 readSizeIO ht = do
-    chainsVec <- readTVarIO $ _chainsVecTV ht
-    return $ V.length chainsVec
+    V.length <$> readTVarIO (_chainsVecTV ht)
 
+{-# INLINABLE readSize #-}
+readSize :: HashTable k v -> STM Int
+readSize ht = do
+    V.length <$> readTVar (_chainsVecTV ht)
 
 -- | Resizes the hash table by scaling it according to the _scaleFactor in the configuration.
 resize :: (Eq k)
@@ -163,7 +166,7 @@
                                writeTVar (_itemsTV newChain) ((k,v):newList)
                       | (k,v) <- listOfNodes ]
 
-                      
+
 -- | Lookup the value for the key in the hash table if it exists.
 {-# INLINABLE lookup #-}
 lookup :: (Eq k) => HashTable k v -> k -> IO (Maybe v)
@@ -268,16 +271,21 @@
         when (migrationStatus == NotStarted) $
             void $ forkIO (resize htable)
 
+-- | The load (i.e. number of stored items) in the table. Note that this is not synchronized for performance reasons and hence might be somewhat out of date if a lot of contention is happening.
+readLoad :: HashTable k v -> IO Int
+readLoad htable = readIORef (_totalLoad htable)
+
 -- Atomically retrieves list of key-value pairs. If there is a lot of contention going on, this may be very inefficient.
-getAssocs :: (Eq k)
+readAssocs :: (Eq k)
             => HashTable k v -> STM [(k,v)]
-getAssocs htable = do
+readAssocs htable = do
     chainsVec <- readTVar $ _chainsVecTV htable
     let len = V.length chainsVec
     let getItemsForChain k = do
             chain <- readChainForIndex htable k
             readTVar (_itemsTV chain)
     msum <$> mapM getItemsForChain [0..len-1]
+
 
 {-# INLINABLE deleteFirstKey #-}
 deleteFirstKey ::  Eq a => a -> [(a,b)] -> [(a,b)]
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -88,7 +88,7 @@
                     [ do res <-  H.lookup chainTable k
                          return $ (isJust res) && (fromJust res == a)
                     | (k,a) <- mapAssocs ]
-    list2 <- run $ atomically $ H.getAssocs chainTable
+    list2 <- run $ atomically $ H.readAssocs chainTable
     -- test if there aren't any duplicates in the Hash Table:
     let res2 = (not . hasDuplicates) list2
     mymap <- run $ readIORef ioref
@@ -106,4 +106,4 @@
     print "------- Map ASSOCS List ----"
     print =<< (M.assocs <$> readIORef ioref)
     print "--------Hashtable AFTER --------"
-    print =<< atomically (H.getAssocs ctable)
+    print =<< atomically (H.readAssocs ctable)
