diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # CHANGELOG
 
+## [v1.0.0.0] - 05/01/2024
+
+* Remove support for GHC 8.10 to 9.0 inclusive
+* `text-display` is now backed by [`text-builder-linear`](https://flora.pm/packages/@hackage/text-builder-linear)
+  * Manual instances will need some adjustments
+  * As a result of the builder's strictness properties, lazy evaluation of lists is dropped
+  * Derived instances should not require adjustments
+
 ## [v0.0.5.2] - 07/04/2024
 
 * Allow GHC 9.6.4 and 9.8.2
diff --git a/src/Data/Text/Display/Core.hs b/src/Data/Text/Display/Core.hs
--- a/src/Data/Text/Display/Core.hs
+++ b/src/Data/Text/Display/Core.hs
@@ -3,6 +3,7 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE LinearTypes #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE StandaloneDeriving #-}
@@ -23,16 +24,18 @@
 module Data.Text.Display.Core where
 
 import Control.Exception hiding (TypeError)
-import Data.ByteString
-import qualified Data.ByteString.Lazy as BL
+import Data.ByteString (StrictByteString)
+import Data.ByteString.Lazy (LazyByteString)
 import Data.Int
 import Data.Kind
+import qualified Data.List as List
 import Data.List.NonEmpty
 import Data.Proxy
 import Data.Text (Text)
-import qualified Data.Text as T
+import qualified Data.Text as Text
+import Data.Text.Builder.Linear (Builder)
+import qualified Data.Text.Builder.Linear as Builder
 import qualified Data.Text.Lazy as TL
-import Data.Text.Lazy.Builder (Builder)
 import qualified Data.Text.Lazy.Builder as TB
 import qualified Data.Text.Lazy.Builder.Int as TB
 import qualified Data.Text.Lazy.Builder.RealFloat as TB
@@ -61,8 +64,8 @@
   -- > import qualified Data.Text.Lazy.Builder as TB
   -- >
   -- > instance Display Char where
-  -- >   displayBuilder c = TB.fromText $ T.singleton c
-  -- >   displayList cs = TB.fromText $ T.pack cs
+  -- >   displayBuilder c = Builder.fromText $ Text.pack $ Text.singleton c
+  -- >   displayList cs = Builder.fromText $ Text.pack $ Text.pack cs
   -- >
   -- > instance (Display a) => Display [a] where
   -- >   -- In this instance, 'displayBuilder' is defined in terms of 'displayList', which for most types
@@ -135,7 +138,7 @@
 --
 -- @since 0.0.1.0
 display :: Display a => a -> Text
-display a = TL.toStrict $ TB.toLazyText $ displayBuilder a
+display a = Builder.runBuilder $ displayBuilder a
 
 -- | 🚫 You should not try to display functions!
 --
@@ -163,7 +166,7 @@
 -- Use 'Data.Text.Encoding.decodeUtf8'' or 'Data.Text.Encoding.decodeUtf8With' to convert from UTF-8
 --
 -- @since 0.0.1.0
-instance CannotDisplayByteStrings => Display ByteString where
+instance CannotDisplayByteStrings => Display StrictByteString where
   displayBuilder = undefined
 
 -- | 🚫 You should not try to display lazy ByteStrings!
@@ -172,7 +175,7 @@
 -- Use 'Data.Text.Encoding.decodeUtf8'' or 'Data.Text.Encoding.decodeUtf8With' to convert from UTF-8
 --
 -- @since 0.0.1.0
-instance CannotDisplayByteStrings => Display BL.ByteString where
+instance CannotDisplayByteStrings => Display LazyByteString where
   displayBuilder = undefined
 
 type family CannotDisplayByteStrings :: Constraint where
@@ -211,7 +214,7 @@
 --
 -- @since 0.0.1.0
 instance KnownSymbol str => Display (OpaqueInstance str a) where
-  displayBuilder _ = TB.fromString $ symbolVal (Proxy @str)
+  displayBuilder _ = Builder.fromText $ Text.pack $ symbolVal (Proxy @str)
 
 -- | This wrapper allows you to rely on a pre-existing 'Show' instance in order to
 -- derive 'Display' from it.
@@ -237,7 +240,7 @@
 --
 -- @since 0.0.1.0
 instance Show e => Display (ShowInstance e) where
-  displayBuilder s = TB.fromString $ show s
+  displayBuilder s = List.foldl' (\acc char -> acc <> Builder.fromChar char) "" $ show s
 
 -- @since 0.0.1.0
 newtype DisplayDecimal e
@@ -247,7 +250,7 @@
 
 -- @since 0.0.1.0
 instance Integral e => Display (DisplayDecimal e) where
-  displayBuilder = TB.decimal
+  displayBuilder = displayBuilder . TB.toLazyText . TB.decimal
 
 -- @since 0.0.1.0
 newtype DisplayRealFloat e
@@ -257,7 +260,7 @@
 
 -- @since 0.0.1.0
 instance RealFloat e => Display (DisplayRealFloat e) where
-  displayBuilder = TB.realFloat
+  displayBuilder = displayBuilder . TB.toLazyText . TB.realFloat
 
 -- | @since 0.0.1.0
 deriving via (ShowInstance ()) instance Display ()
@@ -280,20 +283,20 @@
 instance Display Char where
   -- This instance's implementation is used in the haddocks of the typeclass.
   -- If you change it, reflect the change in the documentation.
-  displayBuilder c = TB.fromText $ T.singleton c
-  displayList cs = TB.fromText $ T.pack cs
+  displayBuilder c = Builder.fromChar c
+  displayList cs = Builder.fromText $ Text.pack cs
 
 -- | Lazy 'TL.Text'
 --
 -- @since 0.0.1.0
 instance Display TL.Text where
-  displayBuilder = TB.fromLazyText
+  displayBuilder = Builder.fromText . TL.toStrict
 
 -- | Strict 'Data.Text.Text'
 --
 -- @since 0.0.1.0
 instance Display Text where
-  displayBuilder = TB.fromText
+  displayBuilder = Builder.fromText
 
 -- | @since 0.0.1.0
 instance Display a => Display [a] where
@@ -309,7 +312,7 @@
 
 -- | @since 0.0.1.0
 instance Display a => Display (NonEmpty a) where
-  displayBuilder (a :| as) = displayBuilder a <> TB.fromString " :| " <> displayBuilder as
+  displayBuilder (a :| as) = displayBuilder a <> Builder.fromText " :| " <> displayBuilder as
 
 -- | @since 0.0.1.0
 instance Display a => Display (Maybe a) where
diff --git a/src/Data/Text/Display/Generic.hs b/src/Data/Text/Display/Generic.hs
--- a/src/Data/Text/Display/Generic.hs
+++ b/src/Data/Text/Display/Generic.hs
@@ -23,9 +23,10 @@
 module Data.Text.Display.Generic where
 
 import Data.Kind
+import qualified Data.List as List
+import Data.Text.Builder.Linear
+import qualified Data.Text.Builder.Linear as Builder
 import Data.Text.Display.Core
-import Data.Text.Lazy.Builder (Builder)
-import qualified Data.Text.Lazy.Builder as TB
 import Data.Type.Bool
 import GHC.Generics
 import GHC.TypeLits
@@ -55,9 +56,9 @@
 
 instance (Constructor c, GDisplay1 f) => GDisplay1 (M1 C c f) where
   gdisplayBuilder1 c@(M1 a)
-    | conIsRecord c = TB.fromString (conName c) <> "\n  { " <> gdisplayBuilder1 a <> "\n  }"
-    | conIsTuple c = TB.fromString (conName c) <> " ( " <> gdisplayBuilder1 a <> " )"
-    | otherwise = TB.fromString (conName c) <> " " <> gdisplayBuilder1 a
+    | conIsRecord c = List.foldl' (\acc char -> acc <> Builder.fromChar char) "" (conName c) <> "\n  { " <> gdisplayBuilder1 a <> "\n  }"
+    | conIsTuple c = List.foldl' (\acc char -> acc <> Builder.fromChar char) "" (conName c) <> " ( " <> gdisplayBuilder1 a <> " )"
+    | otherwise = List.foldl' (\acc char -> acc <> Builder.fromChar char) "" (conName c) <> " " <> gdisplayBuilder1 a
     where
       conIsTuple :: C1 c f p -> Bool
       conIsTuple y =
@@ -70,7 +71,7 @@
   gdisplayBuilder1 s@(M1 a) =
     if selName s == ""
       then gdisplayBuilder1 a
-      else TB.fromString (selName s) <> " = " <> gdisplayBuilder1 a
+      else List.foldl' (\acc char -> acc <> Builder.fromChar char) "" (selName s) <> " = " <> gdisplayBuilder1 a
 
 instance GDisplay1 f => GDisplay1 (M1 D s f) where
   gdisplayBuilder1 (M1 a) = gdisplayBuilder1 a
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -5,21 +5,16 @@
 
 module Main where
 
-import Control.DeepSeq
 import Control.Exception
-import Control.Monad
 import Data.List.NonEmpty
 import qualified Data.List.NonEmpty as NE
-import Data.Maybe
 import qualified Data.Text as T
 import Data.Text.Arbitrary
-import qualified Data.Text.Lazy as TL
-import qualified Data.Text.Lazy.Builder as TB
-import System.Timeout
 import Test.Tasty
 import Test.Tasty.HUnit
 import Test.Tasty.QuickCheck
 
+import qualified Data.Text.Builder.Linear as Builder
 import Data.Text.Display
 
 main :: IO ()
@@ -51,14 +46,6 @@
     (Display)
     via (OpaqueInstance "<opaque>" OpaqueType)
 
--- | @v \`shouldEvaluateWithin\` n@ sets the expectation that evaluating @v@
--- should take no longer than @n@ microseconds.
-shouldEvaluateWithin :: (HasCallStack, NFData a) => a -> Int -> Assertion
-shouldEvaluateWithin a n = do
-  res <- timeout n (evaluate $ force a)
-  when (isNothing res) $ do
-    assertFailure ("evaluation timed out in " <> show n <> " microseconds")
-
 spec :: TestTree
 spec =
   testGroup
@@ -79,9 +66,6 @@
         , testCase "Single-element List instance is equivalent to Show" $ do
             let list = [1] :: [Int]
             T.unpack (display list) @?= show list
-        , testCase "List instance is streamed lazily" $ do
-            let list = [1 ..] :: [Int]
-            TL.take 20 (TB.toLazyText $ displayBuilder list) `shouldEvaluateWithin` 100000
         , testCase "NonEmpty instance is equivalent to Show" $ do
             let ne = NE.fromList [1 .. 5] :: NonEmpty Int
             T.unpack (display ne) @?= show ne
@@ -113,12 +97,12 @@
     , testGroup
         "`displayParen` tests"
         [ testCase "Surrounds with parens when True" $
-            displayParen True "foo" @?= "(foo)"
+            Builder.runBuilder (displayParen True "foo") @?= "(foo)"
         , testCase "Doesn't surround with parens when False" $
-            displayParen False "foo" @?= "foo"
+            Builder.runBuilder (displayParen False "foo") @?= "foo"
         , testCase "Surrounds deeply-nested Maybes with a prec of 10" $
-            displayPrec 10 (Just (Just (Just (3 :: Int)))) @?= "Just (Just (Just 3))"
+            Builder.runBuilder (displayPrec 10 (Just (Just (Just (3 :: Int))))) @?= "Just (Just (Just 3))"
         , testCase "Surrounds deeply-nested Maybes with a prec of 11" $
-            displayPrec 11 (Just (Just (Just (3 :: Int)))) @?= "(Just (Just (Just 3)))"
+            Builder.runBuilder (displayPrec 11 (Just (Just (Just (3 :: Int))))) @?= "(Just (Just (Just 3)))"
         ]
     ]
diff --git a/text-display.cabal b/text-display.cabal
--- a/text-display.cabal
+++ b/text-display.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               text-display
-version:            0.0.5.2
+version:            1.0.0.0
 category:           Text
 synopsis:           A typeclass for user-facing output
 description:
@@ -14,9 +14,6 @@
 maintainer:         Hécate Moonlight
 license:            MIT
 build-type:         Simple
-tested-with:
-  GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.7 || ==9.6.4 || ==9.8.2
-
 extra-source-files:
   LICENSE
   README.md
@@ -35,6 +32,12 @@
   ./doc/book/searchindex.json
   CHANGELOG.md
 
+tested-with:
+  GHC ==9.6.6
+   || ==9.8.4
+   || ==9.10.1
+   || ==9.12.1
+
 flag book
   description: Enable the generation of the book
   default:     False
@@ -65,10 +68,12 @@
     Data.Text.Display
     Data.Text.Display.Core
     Data.Text.Display.Generic
+
   build-depends:
-    , base        >=4.12 && <5.0
-    , bytestring  >=0.10 && <0.13
-    , text        >=2.0
+    , base                 >=4.12  && <5.0
+    , bytestring           >=0.10  && <0.13
+    , text                 >=2.0.2 && <2.2
+    , text-builder-linear  >=0.1.3 && <0.2
 
 executable book
   import:         common-extensions
@@ -81,7 +86,7 @@
     buildable: False
 
   build-depends:
-    , base
+    , base >=4.12 && <5.0
     , directory
     , literatex
     , shake
@@ -94,11 +99,11 @@
   main-is:        Main.hs
   hs-source-dirs: test
   build-depends:
-    , base
-    , deepseq
+    , base >=4.12 && <5.0
     , quickcheck-text
     , tasty
     , tasty-hunit
     , tasty-quickcheck
     , text
+    , text-builder-linear
     , text-display
