diff --git a/Data/Aeson/Encode.hs b/Data/Aeson/Encode.hs
--- a/Data/Aeson/Encode.hs
+++ b/Data/Aeson/Encode.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
 
 -- |
 -- Module:      Data.Aeson.Encode
@@ -8,8 +8,13 @@
 -- Stability:   experimental
 -- Portability: portable
 --
--- Efficiently serialize a JSON value as a lazy 'L.ByteString',
--- encoded as UTF-8.
+-- Efficiently serialize a JSON value.
+--
+-- Most frequently, you'll probably want to encode straight to UTF-8
+-- (the standard JSON encoding) using 'encode'.
+--
+-- You can convert a 'Builder' (as returned by 'fromValue') to a
+-- string using e.g. 'toLazyText'.
 
 module Data.Aeson.Encode
     (
@@ -17,74 +22,73 @@
     , encode
     ) where
 
-import Blaze.ByteString.Builder (Builder, fromByteString, toLazyByteString)
-import Blaze.Text (double, integral)
 import Data.Aeson.Types (ToJSON(..), Value(..))
 import Data.Attoparsec.Number (Number(..))
 import Data.Monoid (mappend)
-import Data.Text.Encoding (encodeUtf8)
+import Data.Text.Lazy.Builder
+import Data.Text.Lazy.Builder.Int (decimal)
+import Data.Text.Lazy.Builder.RealFloat (realFloat)
+import Data.Text.Lazy.Encoding (encodeUtf8)
 import Numeric (showHex)
-import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8
-import qualified Blaze.ByteString.Builder.Char8 as Char8
-import qualified Data.ByteString.Lazy.Char8 as L
+import qualified Data.ByteString.Lazy as L
 import qualified Data.HashMap.Strict as H
 import qualified Data.Text as T
 import qualified Data.Vector as V
 
--- | Encode a JSON value to a 'Builder'.
+-- | Encode a JSON value to a 'Builder'.  You can convert this to a
+-- string using e.g. 'toLazyText', or encode straight to UTF-8 (the
+-- standard JSON encoding) using 'encode'.
 fromValue :: Value -> Builder
-fromValue Null = {-# SCC "fromValue/Null" #-} fromByteString "null"
+fromValue Null = {-# SCC "fromValue/Null" #-} "null"
 fromValue (Bool b) = {-# SCC "fromValue/Bool" #-}
-                     if b then fromByteString "true"
-                     else fromByteString "false"
+                     if b then "true" else "false"
 fromValue (Number n) = {-# SCC "fromValue/Number" #-} fromNumber n
 fromValue (String s) = {-# SCC "fromValue/String" #-} string s
 fromValue (Array v)
-    | V.null v = {-# SCC "fromValue/Array" #-} fromByteString "[]"
+    | V.null v = {-# SCC "fromValue/Array" #-} "[]"
     | otherwise = {-# SCC "fromValue/Array" #-}
-                  Char8.fromChar '[' `mappend`
-                  fromValue (V.unsafeHead v) `mappend`
-                  V.foldr f (Char8.fromChar ']') (V.unsafeTail v)
-  where f a z = Char8.fromChar ',' `mappend` fromValue a `mappend` z
+                  singleton '[' <>
+                  fromValue (V.unsafeHead v) <>
+                  V.foldr f (singleton ']') (V.unsafeTail v)
+  where f a z = singleton ',' <> fromValue a <> z
 fromValue (Object m) = {-# SCC "fromValue/Object" #-}
     case H.toList m of
-      (x:xs) -> Char8.fromChar '{' `mappend`
-                one x `mappend` foldr f (Char8.fromChar '}') xs
-      _      -> fromByteString "{}"
-  where f a z     = Char8.fromChar ',' `mappend` one a `mappend` z
-        one (k,v) = string k `mappend` Char8.fromChar ':' `mappend` fromValue v
+      (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs
+      _      -> "{}"
+  where f a z     = singleton ',' <> one a <> z
+        one (k,v) = string k <> singleton ':' <> fromValue v
 
 string :: T.Text -> Builder
-string s = Char8.fromChar '"' `mappend` (quote s) `mappend` Char8.fromChar '"'
+string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'
   where
     quote q = case T.uncons t of
-                Just (c,t') -> fromText h `mappend` escape c `mappend` quote t'
                 Nothing     -> fromText h
-        where (h,t) = T.break isEscape q
+                Just (!c,t') -> fromText h <> escape c <> quote t'
+        where (h,t) = {-# SCC "break" #-} T.break isEscape q
     isEscape c = c == '\"' || c == '\\' || c < '\x20'
-    escape '\"' = fromByteString "\\\""
-    escape '\\' = fromByteString "\\\\"
-    escape '\n' = fromByteString "\\n"
-    escape '\r' = fromByteString "\\r"
-    escape '\t' = fromByteString "\\t"
+    escape '\"' = "\\\""
+    escape '\\' = "\\\\"
+    escape '\n' = "\\n"
+    escape '\r' = "\\r"
+    escape '\t' = "\\t"
     escape c
-        | c < '\x20' = Char8.fromString $
-                       "\\u" ++ replicate (4 - length h) '0' ++ h
-        | otherwise  = Utf8.fromChar c
+        | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h
+        | otherwise  = singleton c
         where h = showHex (fromEnum c) ""
 
--- The version in blaze-builder is way slower.
-fromText :: T.Text -> Builder
-fromText t = fromByteString (encodeUtf8 t)
-
 fromNumber :: Number -> Builder
-fromNumber (I i) = integral i
+fromNumber (I i) = decimal i
 fromNumber (D d)
-    | isNaN d || isInfinite d = fromByteString "null"
-    | otherwise               = double d
+    | isNaN d || isInfinite d = "null"
+    | otherwise               = realFloat d
 
 -- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
 encode :: ToJSON a => a -> L.ByteString
-encode = {-# SCC "encode" #-} toLazyByteString . fromValue .
+encode = {-# SCC "encode" #-} encodeUtf8 . toLazyText . fromValue .
          {-# SCC "toJSON" #-} toJSON
 {-# INLINE encode #-}
+
+(<>) :: Builder -> Builder -> Builder
+(<>) = mappend
+{-# INLINE (<>) #-}
+infixr 6 <>
diff --git a/aeson.cabal b/aeson.cabal
--- a/aeson.cabal
+++ b/aeson.cabal
@@ -1,5 +1,5 @@
 name:            aeson
-version:         0.4.0.1
+version:         0.5.0.0
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Web, JSON
@@ -122,7 +122,6 @@
     attoparsec >= 0.8.6.1,
     base == 4.*,
     blaze-builder >= 0.2.1.4,
-    blaze-textual >= 0.2.0.2,
     bytestring,
     containers,
     deepseq,
diff --git a/benchmarks/aeson-benchmarks.cabal b/benchmarks/aeson-benchmarks.cabal
--- a/benchmarks/aeson-benchmarks.cabal
+++ b/benchmarks/aeson-benchmarks.cabal
@@ -8,7 +8,7 @@
   main-is: CompareWithJSON.hs
   ghc-options: -Wall -O2
   build-depends:
-    aeson == 0.4.0.0,
+    aeson,
     base,
     blaze-builder,
     bytestring,
@@ -19,14 +19,14 @@
   main-is: AesonEncode.hs
   ghc-options: -Wall -O2
   build-depends:
-    aeson == 0.4.0.0,
+    aeson,
     base
 
 executable aeson-benchmark-aeson-parse
   main-is: AesonParse.hs
   ghc-options: -Wall -O2
   build-depends:
-    aeson == 0.4.0.0,
+    aeson,
     attoparsec,
     base
 
diff --git a/release-notes.markdown b/release-notes.markdown
--- a/release-notes.markdown
+++ b/release-notes.markdown
@@ -1,3 +1,14 @@
+# 0.4 to 0.5
+
+When used with the UTF-8 encoding performance improvements introduced
+in version 0.11.1.12 of the text package, this release improves
+aeson's JSON encoding performance by 33% relative to aeson 0.4.
+
+As part of achieving this improvement, an API change was necessary.
+The `fromValue` function in the `Data.Aeson.Encode` module now uses
+the text package's `Builder` type instead of the blaze-builder
+package's `Builder` type.
+
 # 0.3 to 0.4
 
 ## Ease of use
