diff --git a/combobuffer.cabal b/combobuffer.cabal
--- a/combobuffer.cabal
+++ b/combobuffer.cabal
@@ -1,5 +1,5 @@
 Name:                combobuffer
-Version:             0.1
+Version:             0.2
 Synopsis:            Various buffer implementations
 Description:         Various buffer implementations
 Homepage:            https://github.com/JohnLato/combobuffer
@@ -21,10 +21,11 @@
                      ,Data.RingBuffer.SeqBuffer
                      ,Data.RingBuffer.SVec
                      ,Data.RingBuffer.TGen
+                     ,Data.RingBuffer.Vector
 
   Build-depends:      base         >= 3      && < 5
                      ,containers   >= 0.3    && < 0.6
-                     ,template-haskell >= 2.6 && < 2.9
+                     ,template-haskell
                      -- ,type-level   >= 0.2    && < 0.3
                      -- ,tuple        >= 0.2    && < 0.3
                      ,vector       >= 0.5    && < 0.11
diff --git a/src/Data/RingBuffer/TGen.hs b/src/Data/RingBuffer/TGen.hs
--- a/src/Data/RingBuffer/TGen.hs
+++ b/src/Data/RingBuffer/TGen.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
@@ -38,7 +39,11 @@
   let fields = replicate sz (IsStrict, elname)
   in return [DataD [] nm binders [NormalC nm fields] []]
 
+#if MIN_VERSION_template_haskell(2,9,0)
+mkElInst tname elname = return [TySynInstD ''El $ TySynEqn [tname] (elname) ]
+#else
 mkElInst tname elname = return [TySynInstD ''El [tname] (elname) ]
+#endif
 
 mkInitInst vsz nm tname = let nmStr = show nm in [d| instance Initializable $(tname) where {-# INLINE newInit #-}; newInit el sz | sz >= 0 && sz <= vsz = $(appsE $ conE nm:replicate vsz [| el |]) ; newInit el sz = error ("cannot initialize " ++ nmStr ++ " with size: " ++ show sz) |]
 
diff --git a/src/Data/RingBuffer/Vector.hs b/src/Data/RingBuffer/Vector.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/RingBuffer/Vector.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeFamilies #-}
+
+{-# OPTIONS_GHC -Wall -funbox-strict-fields #-}
+
+-- | A vector-based 'RingBuffer'implementation
+module Data.RingBuffer.Vector (
+  VBuffer
+)
+
+where
+
+import Prelude hiding (length)
+
+import qualified Data.Vector.Unboxed as V
+import qualified Data.Vector.Unboxed.Mutable as VM
+import Control.Exception
+import Control.Monad
+import Data.IORef
+import System.IO.Unsafe (unsafePerformIO)
+
+import Data.RingBuffer.Class
+
+data VBuffer el = VBuffer
+    { size       :: !Int
+    , offset     :: !Int
+    , fullBuffer :: !(V.Vector el)
+    , partial    :: !(V.Vector el)
+    , stale      :: IORef Bool
+    } deriving (Eq)
+
+{-
+class RingBuffer c where
+  length    :: c -> Int
+  push      :: c -> El c -> c
+  (!)       :: c -> Int  -> El c
+  slice     :: c -> Int  -> Int -> [El c]
+  {-# INLINE slice #-}
+  slice c start num = [ c ! ix | ix <- [start .. start+num]]
+-}
+
+type instance El (VBuffer el) = el
+
+instance V.Unbox el => Initializable (VBuffer el) where
+  {-# INLINE newInit #-}
+  newInit val size = unsafePerformIO $ do
+      -- we need to make sure that the two vectors aren't shared, and CSE may
+      -- common them up if we just do (V.replicate size val)
+      fullBuffer <- V.unsafeFreeze =<< VM.replicate size val
+      partial <- V.unsafeFreeze =<< VM.replicate size val
+      stale <- newIORef False
+      let offset = 0
+      return $ VBuffer { size, offset, fullBuffer, partial, stale }
+
+instance V.Unbox el => RingBuffer (VBuffer el) where
+  {-# INLINE length #-}
+  length      = size
+  {-# INLINE (!) #-}
+  (!)         = index
+  {-# INLINE push #-}
+  push = pushBuf
+  -- {-# INLINE slice #-}
+  -- slice vec start num = V.toList $ V.slice start num vec
+
+index :: (V.Unbox el) => VBuffer el -> Int -> el
+index VBuffer{..} ix =
+    if ix < offset
+        then partial `V.unsafeIndex` ((offset-ix)-1)
+        else fullBuffer `V.unsafeIndex` (size + offset - ix - 1)
+
+pushBuf :: (V.Unbox el) => VBuffer el -> el -> VBuffer el
+pushBuf VBuffer{..} el = unsafePerformIO $ do
+    isStale <- atomicModifyIORef stale (True,)
+    when isStale (throwIO $ ErrorCall "VBuffer: attempt to push to stale buffer")
+    if offset < size
+        then do
+            v <- V.unsafeThaw partial
+            VM.unsafeWrite v offset el
+            newPartial <- V.unsafeFreeze v
+            stale' <- newIORef False
+            return $ VBuffer { size, offset=offset+1, fullBuffer
+                             , partial=newPartial
+                             , stale=stale' }
+        else do
+            stale' <- newIORef False
+            return $ VBuffer { size, offset=1
+                             , fullBuffer=partial
+                             , partial = V.replicate size el
+                             , stale = stale'}
