diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+1.2.0.3
+-------
+
+- Performance improvements during metadata encoding.
+
 1.2.0.2
 -------
 - Bump `vector` upper bound.
diff --git a/Geography/VectorTile/Protobuf/Internal.hs b/Geography/VectorTile/Protobuf/Internal.hs
--- a/Geography/VectorTile/Protobuf/Internal.hs
+++ b/Geography/VectorTile/Protobuf/Internal.hs
@@ -8,7 +8,7 @@
 
 -- |
 -- Module    : Geography.VectorTile.Protobuf.Internal
--- Copyright : (c) Azavea, 2016
+-- Copyright : (c) Azavea, 2016 - 2017
 -- License   : Apache 2
 -- Maintainer: Colin Woodbury <cwoodbury@azavea.com>
 --
@@ -56,7 +56,7 @@
 import           Data.Bits
 import           Data.Foldable (foldrM, foldlM)
 import           Data.Int
-import           Data.List (nub, elemIndex)
+import           Data.List (nub)
 import qualified Data.Map.Lazy as M
 import           Data.Maybe (fromJust)
 import           Data.Monoid
@@ -113,9 +113,10 @@
                           , _values = putField $ map toProtobuf vs
                           , _extent = putField . Just . fromIntegral $ VT._extent l }
     where (ks,vs) = totalMeta (VT._points l) (VT._linestrings l) (VT._polygons l)
-          fs = V.toList $ V.concat [ V.map (unfeature ks vs Point) (VT._points l)
-                                   , V.map (unfeature ks vs LineString) (VT._linestrings l)
-                                   , V.map (unfeature ks vs Polygon) (VT._polygons l) ]
+          (km,vm) = (M.fromList $ zip ks [0..], M.fromList $ zip vs [0..])
+          fs = V.toList $ V.concat [ V.map (unfeature km vm Point) (VT._points l)
+                                   , V.map (unfeature km vm LineString) (VT._linestrings l)
+                                   , V.map (unfeature km vm Polygon) (VT._polygons l) ]
 
 instance Protobuffable VT.Val where
   fromProtobuf v = mtoe "Value decode: No legal Value type offered" $ fmap VT.St (getField $ _string v)
@@ -360,19 +361,18 @@
 totalMeta ps ls polys = (keys, vals)
   where keys = S.toList . S.unions $ f ps <> f ls <> f polys
         vals = nub . concat $ g ps <> g ls <> g polys  -- `nub` is O(n^2)
-        f = V.foldr (\x acc -> M.keysSet (VT._metadata x) : acc) []
-        g = V.foldr (\x acc -> M.elems (VT._metadata x) : acc) []
+        f = V.foldr (\feat acc -> M.keysSet (VT._metadata feat) : acc) []
+        g = V.foldr (\feat acc -> M.elems (VT._metadata feat) : acc) []
 
 -- | Encode a high-level `Feature` back into its mid-level `RawFeature` form.
-unfeature :: ProtobufGeom g => [Text] -> [VT.Val] -> GeomType -> VT.Feature g -> RawFeature
+unfeature :: ProtobufGeom g => M.Map Text Int -> M.Map VT.Val Int -> GeomType -> VT.Feature g -> RawFeature
 unfeature keys vals gt fe = RawFeature
                             { _featureId = putField . Just . fromIntegral $ VT._featureId fe
                             , _tags = putField $ tags fe
                             , _geom = putField $ Just gt
-                            , _geometries = putField . uncommands . toCommands $ VT._geometries fe
-                            }
+                            , _geometries = putField . uncommands . toCommands $ VT._geometries fe }
   where tags = unpairs . map f . M.toList . VT._metadata
-        f (k,v) = both (fromIntegral . fromJust) (k `elemIndex` keys, v `elemIndex` vals)
+        f (k,v) = both (fromIntegral . fromJust) (M.lookup k keys, M.lookup v vals)
 
 {- UTIL -}
 
diff --git a/Geography/VectorTile/VectorTile.hs b/Geography/VectorTile/VectorTile.hs
--- a/Geography/VectorTile/VectorTile.hs
+++ b/Geography/VectorTile/VectorTile.hs
@@ -3,7 +3,7 @@
 
 -- |
 -- Module    : Geography.VectorTile.VectorTile
--- Copyright : (c) Azavea, 2016
+-- Copyright : (c) Azavea, 2016 - 2017
 -- License   : Apache 2
 -- Maintainer: Colin Woodbury <cwoodbury@azavea.com>
 --
@@ -137,6 +137,6 @@
 -- | Legal Metadata /Value/ types. Note that `S64` are Z-encoded automatically
 -- by the underlying "Data.ProtocolBuffers" library.
 data Val = St Text | Fl Float | Do Double | I64 Int64 | W64 Word64 | S64 Int64 | B Bool
-         deriving (Eq,Show,Generic)
+         deriving (Eq,Ord,Show,Generic)
 
 instance NFData Val
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -24,22 +24,25 @@
   ls <- BS.readFile "test/linestring.mvt"
   pl <- BS.readFile "test/polygon.mvt"
   rd <- BS.readFile "test/roads.mvt"
-  defaultMain $ suite op ls pl rd
+  cl <- BS.readFile "test/clearlake.mvt"
+  defaultMain $ suite op ls pl rd cl
 
 {- SUITES -}
 
-suite :: BS.ByteString -> BS.ByteString -> BS.ByteString -> BS.ByteString -> TestTree
-suite op ls pl rd = testGroup "Unit Tests"
+suite :: BS.ByteString -> BS.ByteString -> BS.ByteString -> BS.ByteString -> BS.ByteString -> TestTree
+suite op ls pl rd cl = testGroup "Unit Tests"
   [ testGroup "Protobuf"
     [ testGroup "Decoding"
       [ testCase "onepoint.mvt -> Raw.Tile" $ testOnePoint op
       , testCase "linestring.mvt -> Raw.Tile" $ testLineString ls
       , testCase "polygon.mvt -> Raw.Tile" $ testPolygon pl
       , testCase "roads.mvt -> Raw.Tile" $ testDecode rd
+      , testCase "clearlake.mvt -> Raw.Tile" $ testDecode cl
       , testCase "onepoint.mvt -> VectorTile" $ tileDecode op
       , testCase "linestring.mvt -> VectorTile" $ tileDecode ls
       , testCase "polygon.mvt -> VectorTile" $ tileDecode pl
       , testCase "roads.mvt -> VectorTile" $ tileDecode rd
+      , testCase "clearlake.mvt -> VectorTile" $ tileDecode cl
       ]
     , testGroup "Encoding"
       [ testGroup "RawVectorTile <-> VectorTile"
diff --git a/vectortiles.cabal b/vectortiles.cabal
--- a/vectortiles.cabal
+++ b/vectortiles.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                vectortiles
-version:             1.2.0.2
+version:             1.2.0.3
 synopsis:            GIS Vector Tiles, as defined by Mapbox.
 description:         GIS Vector Tiles, as defined by Mapbox.
                      .
