diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,12 @@
+## 0.8.0.6 (2018-02-04)
+
+Fixes:
+
+  - Don't run time-sensitive tests by default (fixes spurious failures
+    on loaded CI servers).
+
+  - Work around order-sensitive `toJSON` decoding in doctests.
+
 ## 0.8.0.5 (2018-02-04)
 
 Changes:
diff --git a/mellon-web.cabal b/mellon-web.cabal
--- a/mellon-web.cabal
+++ b/mellon-web.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 55af04fb959faaa66f7f850ad4ce3d6ebb14a32c54b20fb5450b1fe5a51ef64a
+-- hash: 1f6be6c884c3ebe5ad3e9cc23e01642a2104485a9d38263856e26947381a37b0
 
 name:                   mellon-web
-version:                0.8.0.5
+version:                0.8.0.6
 synopsis:               A REST web service for Mellon controllers
 description:            The @mellon-web@ package wraps a @mellon-core@ controller in a REST
                         web service, making it possible to control physical access devices
@@ -62,6 +62,11 @@
   manual: True
   default: True
 
+flag enable-timing-sensitive-tests
+  description: Enable tests that are timing-sensitive (may fail on loaded machines like CI servers)
+  manual: True
+  default: False
+
 flag gpio-example
   description: Build the GPIO server example
   manual: True
@@ -266,7 +271,7 @@
   hs-source-dirs:
       test
   default-extensions: NoImplicitPrelude
-  other-extensions: OverloadedStrings ScopedTypeVariables
+  other-extensions: CPP OverloadedStrings ScopedTypeVariables
   ghc-options: -w -threaded -rtsopts -with-rtsopts=-N
   build-depends:
       QuickCheck >=2.8 && <2.12
@@ -303,6 +308,8 @@
     ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
   else
     ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if flag(enable-timing-sensitive-tests)
+    cpp-options: -DENABLE_TIMING_SENSITIVE_TESTS
   other-modules:
       Mellon.Web.ClientSpec
       Mellon.Web.ServerSpec
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -1,5 +1,5 @@
 name:       mellon-web
-version:    0.8.0.5
+version:    0.8.0.6
 synopsis:   A REST web service for Mellon controllers
 category:   Web
 stability:  experimental
@@ -64,6 +64,10 @@
     description: Build doctests
     manual: true
     default: true
+  enable-timing-sensitive-tests:
+    description: Enable tests that are timing-sensitive (may fail on loaded machines like CI servers)
+    manual: true
+    default: false
   gpio-example:
     description: Build the GPIO server example
     manual: true
@@ -180,6 +184,7 @@
     source-dirs:
       - test
     other-extensions:
+      - CPP
       - OverloadedStrings
       - ScopedTypeVariables
     ghc-options:
@@ -187,6 +192,9 @@
       - -threaded
       - -rtsopts
       - -with-rtsopts=-N
+    when:
+      - condition: flag(enable-timing-sensitive-tests)
+        cpp-options: -DENABLE_TIMING_SENSITIVE_TESTS
     dependencies:
       - base
       - QuickCheck           >=2.8   && <2.12
diff --git a/src/Mellon/Web/Server/API.hs b/src/Mellon/Web/Server/API.hs
--- a/src/Mellon/Web/Server/API.hs
+++ b/src/Mellon/Web/Server/API.hs
@@ -71,8 +71,8 @@
 
 -- $setup
 -- >>> :set -XOverloadedStrings
--- >>> import Data.String (String)
 -- >>> import Data.Aeson (eitherDecode, encode)
+-- >>> import Data.String (String)
 -- >>> import Data.Swagger.Schema.Validation
 
 wrapBody :: Monad m => HtmlT m () -> HtmlT m a -> HtmlT m a
@@ -123,15 +123,17 @@
 untilSeries :: UTCTime -> Series
 untilSeries t = untilName .= t
 
+-- Aeson 'Object' is unordered, so we have to be careful when
+-- validating values here.
+
 -- $
 -- >>> toJSON Locked
 -- Object (fromList [("state",String "Locked")])
--- >>> toJSON $ Unlocked sampleDate
--- Object (fromList [("state",String "Unlocked"),("until",String "2015-10-06T00:00:00Z")])
 -- >>> encode $ toJSON Locked
 -- "{\"state\":\"Locked\"}"
--- >>> encode $ toJSON $ Unlocked sampleDate
--- "{\"state\":\"Unlocked\",\"until\":\"2015-10-06T00:00:00Z\"}"
+-- >>> let x = encode $ toJSON $ Unlocked sampleDate
+-- >>> x == "{\"state\":\"Unlocked\",\"until\":\"2015-10-06T00:00:00Z\"}" || x == "{\"until\":\"2015-10-06T00:00:00Z\",\"state\":\"Unlocked\"}"
+-- True
 instance ToJSON State where
   toJSON Locked = object [lockedPair]
   toJSON (Unlocked time) = object [unlockedPair, untilPair time]
diff --git a/test/Mellon/Web/ServerSpec.hs b/test/Mellon/Web/ServerSpec.hs
--- a/test/Mellon/Web/ServerSpec.hs
+++ b/test/Mellon/Web/ServerSpec.hs
@@ -1,4 +1,5 @@
 {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-incomplete-uni-patterns #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
@@ -101,6 +102,7 @@
                     secondResponse <- get "/state"
                     liftIO $ decode (simpleBody secondResponse) `shouldBe` Just Locked
 
+#ifdef ENABLE_TIMING_SENSITIVE_TESTS
      describe "Unlocking" $
        do with runApp $
             do it "expires at the specified date" $
@@ -126,6 +128,7 @@
                     liftIO $ sleep 9
                     secondResponse <- get "/state"
                     liftIO $ decode (simpleBody secondResponse) `shouldBe` Just Locked
+#endif
 
      describe "Locking" $
        do with runApp $
