diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2016 Josh Clayton
+Copyright (c) 2016-2017 Josh Clayton
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
diff --git a/app/App.hs b/app/App.hs
--- a/app/App.hs
+++ b/app/App.hs
@@ -21,7 +21,7 @@
 import           Unused.ResponseFilter (withOneOccurrence, withLikelihoods, ignoringPaths)
 import           Unused.ResultsClassifier (ParseConfigError, LanguageConfiguration(..), loadAllConfigurations)
 import           Unused.TagsSource (TagSearchOutcome, loadTagsFromFile, loadTagsFromPipe)
-import           Unused.TermSearch (SearchResults(..), SearchTerm, fromResults)
+import           Unused.TermSearch (SearchResults(..), SearchBackend(..), SearchTerm, fromResults)
 import           Unused.Types (TermMatchSet, RemovalLikelihood(..))
 
 type AppConfig = MonadReader Options
@@ -45,6 +45,7 @@
     , oWithoutCache :: Bool
     , oFromStdIn :: Bool
     , oCommitCount :: Maybe Int
+    , oSearchBackend :: SearchBackend
     }
 
 runProgram :: Options -> IO ()
@@ -57,9 +58,13 @@
     terms <- termsWithAlternatesFromConfig
 
     liftIO $ renderHeader terms
-    results <- withCache . (`executeSearch` terms) =<< searchRunner
+    backend <- searchBackend
+    results <- withCache . flip (executeSearch backend) terms =<< searchRunner
 
     printResults =<< retrieveGitContext =<< fmap (`parseResults` results) loadAllConfigs
+
+searchBackend :: AppConfig m => m SearchBackend
+searchBackend = asks oSearchBackend
 
 termsWithAlternatesFromConfig :: App [SearchTerm]
 termsWithAlternatesFromConfig = do
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -6,6 +6,7 @@
 import           Options.Applicative
 import           Unused.CLI (SearchRunner(..))
 import           Unused.Grouping (CurrentGrouping(..))
+import           Unused.TermSearch (SearchBackend(..))
 import           Unused.Types (RemovalLikelihood(..))
 import           Unused.Util (stringToInt)
 
@@ -38,6 +39,7 @@
     <*> parseWithoutCache
     <*> parseFromStdIn
     <*> parseCommitCount
+    <*> parseSearchBackend
 
 parseSearchRunner :: Parser SearchRunner
 parseSearchRunner =
@@ -116,3 +118,17 @@
     commitParser = optional $ strOption $
         long "commits"
         <> help "Number of recent commit SHAs to display per token"
+
+parseSearchBackend :: Parser SearchBackend
+parseSearchBackend = M.fromMaybe Ag <$> maybeBackend
+  where
+    maybeBackend = optional $ parseBackend <$> parseBackendOption
+    parseBackendOption =
+        strOption $
+        long "search"
+        <> help "[Allowed: ag, rg] Select searching backend"
+
+parseBackend :: String -> SearchBackend
+parseBackend "ag" = Ag
+parseBackend "rg" = Rg
+parseBackend _ = Ag
diff --git a/src/Unused/Aliases.hs b/src/Unused/Aliases.hs
--- a/src/Unused/Aliases.hs
+++ b/src/Unused/Aliases.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Unused.Aliases
     ( groupedTermsAndAliases
     , termsAndAliases
diff --git a/src/Unused/CLI/Search.hs b/src/Unused/CLI/Search.hs
--- a/src/Unused/CLI/Search.hs
+++ b/src/Unused/CLI/Search.hs
@@ -16,11 +16,11 @@
     U.resetScreen
     V.analysisHeader terms
 
-executeSearch :: SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults
-executeSearch runner terms = do
+executeSearch :: TS.SearchBackend -> SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults
+executeSearch backend runner terms = do
     renderHeader terms
-    runSearch runner terms <* U.resetScreen
+    runSearch backend runner terms <* U.resetScreen
 
-runSearch :: SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults
-runSearch SearchWithProgress    = I.progressWithIndicator TS.search I.createProgressBar
-runSearch SearchWithoutProgress = I.progressWithIndicator TS.search I.createSpinner
+runSearch :: TS.SearchBackend -> SearchRunner -> [TS.SearchTerm] -> IO TS.SearchResults
+runSearch b SearchWithProgress    = I.progressWithIndicator (TS.search b) I.createProgressBar
+runSearch b SearchWithoutProgress = I.progressWithIndicator (TS.search b) I.createSpinner
diff --git a/src/Unused/Cache.hs b/src/Unused/Cache.hs
--- a/src/Unused/Cache.hs
+++ b/src/Unused/Cache.hs
@@ -23,21 +23,19 @@
 writeCache :: ToRecord a => [a] -> Cache [a]
 writeCache [] = return []
 writeCache contents = do
-    liftIO $ D.createDirectoryIfMissing True cacheDirectory
-    (CacheFileName fileName) <- ask
-    liftIO $ BS.writeFile fileName $ encode contents
+    ensureCacheDirectoryExists
+    writeContentsToCacheFile contents =<< ask
     return contents
 
 readCache :: FromRecord a => Cache (Maybe [a])
-readCache = do
-    (CacheFileName fileName) <- ask
-
+readCache =
     either
         (const Nothing)
         (processCsv . decode NoHeader)
-        <$> liftIO (safeReadFile fileName)
+        <$> (readFromCache =<< ask)
   where
     processCsv = either (const Nothing) (Just . V.toList)
+    readFromCache (CacheFileName fileName) = liftIO $ safeReadFile fileName
 
 cacheFileName :: String -> IO (Either FingerprintOutcome CacheFileName)
 cacheFileName context = do
@@ -48,3 +46,11 @@
 
 cacheDirectory :: String
 cacheDirectory = "tmp/unused"
+
+ensureCacheDirectoryExists :: Cache ()
+ensureCacheDirectoryExists =
+    liftIO $ D.createDirectoryIfMissing True cacheDirectory
+
+writeContentsToCacheFile :: ToRecord a => [a] -> CacheFileName -> Cache ()
+writeContentsToCacheFile contents (CacheFileName fileName) =
+    liftIO $ BS.writeFile fileName $ encode contents
diff --git a/src/Unused/GitContext.hs b/src/Unused/GitContext.hs
--- a/src/Unused/GitContext.hs
+++ b/src/Unused/GitContext.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Unused.GitContext
     ( gitContextForResults
     ) where
diff --git a/src/Unused/Projection.hs b/src/Unused/Projection.hs
--- a/src/Unused/Projection.hs
+++ b/src/Unused/Projection.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Unused.Projection where
 
 import qualified Data.Bifunctor as BF
diff --git a/src/Unused/ResultsClassifier/Types.hs b/src/Unused/ResultsClassifier/Types.hs
--- a/src/Unused/ResultsClassifier/Types.hs
+++ b/src/Unused/ResultsClassifier/Types.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE FlexibleInstances #-}
 
 module Unused.ResultsClassifier.Types
@@ -14,8 +13,8 @@
 import qualified Control.Monad as M
 import qualified Data.HashMap.Strict as HM
 import qualified Data.List as L
-import qualified Data.Text as T
 import           Data.Text (Text)
+import qualified Data.Text as T
 import           Data.Yaml (FromJSON(..), (.:), (.:?), (.!=))
 import qualified Data.Yaml as Y
 import           Unused.Projection
diff --git a/src/Unused/TagsSource.hs b/src/Unused/TagsSource.hs
--- a/src/Unused/TagsSource.hs
+++ b/src/Unused/TagsSource.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Unused.TagsSource
     ( TagSearchOutcome(..)
     , loadTagsFromFile
diff --git a/src/Unused/TermSearch.hs b/src/Unused/TermSearch.hs
--- a/src/Unused/TermSearch.hs
+++ b/src/Unused/TermSearch.hs
@@ -1,20 +1,33 @@
 module Unused.TermSearch
     ( SearchResults(..)
+    , SearchBackend(..)
     , SearchTerm
     , search
     ) where
 
 import qualified Data.Maybe as M
+import           GHC.IO.Exception (ExitCode(ExitSuccess))
 import qualified System.Process as P
 import           Unused.TermSearch.Internal (commandLineOptions, parseSearchResult)
-import           Unused.TermSearch.Types (SearchResults(..))
+import           Unused.TermSearch.Types (SearchResults(..), SearchBackend(..))
 import           Unused.Types (SearchTerm, searchTermToString)
 
-search :: SearchTerm -> IO SearchResults
-search t =
-    SearchResults . M.mapMaybe (parseSearchResult t) <$> (lines <$> ag (searchTermToString t))
+search :: SearchBackend -> SearchTerm -> IO SearchResults
+search backend t =
+    SearchResults . M.mapMaybe (parseSearchResult backend t) <$> (lines <$> performSearch backend (searchTermToString t))
 
-ag :: String -> IO String
-ag t = do
-  (_, results, _) <- P.readProcessWithExitCode "ag" (commandLineOptions t) ""
-  return results
+performSearch :: SearchBackend -> String -> IO String
+performSearch b t = extractSearchResults b <$> searchOutcome
+  where
+    searchOutcome =
+        P.readProcessWithExitCode
+            (backendToCommand b)
+            (commandLineOptions b t)
+            ""
+    backendToCommand Rg = "rg"
+    backendToCommand Ag = "ag"
+
+extractSearchResults :: SearchBackend -> (ExitCode, String, String) -> String
+extractSearchResults Rg (ExitSuccess, stdout, _) = stdout
+extractSearchResults Rg (_, _, stderr) = stderr
+extractSearchResults Ag (_, stdout, _) = stdout
diff --git a/src/Unused/TermSearch/Internal.hs b/src/Unused/TermSearch/Internal.hs
--- a/src/Unused/TermSearch/Internal.hs
+++ b/src/Unused/TermSearch/Internal.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Unused.TermSearch.Internal
     ( commandLineOptions
     , parseSearchResult
@@ -8,26 +6,38 @@
 import qualified Data.Char as C
 import qualified Data.Maybe as M
 import qualified Data.Text as T
+import           Unused.TermSearch.Types (SearchBackend(..))
 import           Unused.Types (SearchTerm(..), TermMatch(..))
 import           Unused.Util (stringToInt)
 
-commandLineOptions :: String -> [String]
-commandLineOptions t =
+commandLineOptions :: SearchBackend -> String -> [String]
+commandLineOptions backend t =
     if regexSafeTerm t
-        then ["(\\W|^)" ++ t ++ "(\\W|$)", "."] ++ baseFlags
-        else [t, ".", "-Q"] ++ baseFlags
-  where
-    baseFlags = ["-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+        then regexFlags backend t ++ baseFlags backend
+        else nonRegexFlags backend t ++ baseFlags backend
 
-parseSearchResult :: SearchTerm -> String -> Maybe TermMatch
-parseSearchResult term =
-    maybeTermMatch . map T.unpack . T.splitOn ":" . T.pack
+parseSearchResult :: SearchBackend -> SearchTerm -> String -> Maybe TermMatch
+parseSearchResult backend term =
+    maybeTermMatch backend . map T.unpack . T.splitOn ":" . T.pack
   where
-    maybeTermMatch [_, path, count] = Just $ toTermMatch term path $ countInt count
-    maybeTermMatch _ = Nothing
+    maybeTermMatch Rg [path, count] = Just $ toTermMatch term path $ countInt count
+    maybeTermMatch Rg _ = Nothing
+    maybeTermMatch Ag [_, path, count] = Just $ toTermMatch term path $ countInt count
+    maybeTermMatch Ag _ = Nothing
     countInt = M.fromMaybe 0 . stringToInt
     toTermMatch (OriginalTerm t) path = TermMatch t path Nothing
     toTermMatch (AliasTerm t a) path = TermMatch t path (Just a)
 
 regexSafeTerm :: String -> Bool
 regexSafeTerm = all (\c -> C.isAlphaNum c || c == '_' || c == '-')
+
+nonRegexFlags :: SearchBackend -> String -> [String]
+nonRegexFlags Rg t = [t, ".", "-F"]
+nonRegexFlags Ag t = [t, ".", "-Q"]
+
+baseFlags :: SearchBackend -> [String]
+baseFlags Rg = ["-c", "-j", "1"]
+baseFlags Ag = ["-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+
+regexFlags :: SearchBackend -> String -> [String]
+regexFlags _ t = ["(\\W|^)" ++ t ++ "(\\W|$)", "."]
diff --git a/src/Unused/TermSearch/Types.hs b/src/Unused/TermSearch/Types.hs
--- a/src/Unused/TermSearch/Types.hs
+++ b/src/Unused/TermSearch/Types.hs
@@ -2,8 +2,11 @@
 
 module Unused.TermSearch.Types
     ( SearchResults(..)
+    , SearchBackend(..)
     ) where
 
 import Unused.Types (TermMatch)
+
+data SearchBackend = Ag | Rg
 
 newtype SearchResults = SearchResults { fromResults :: [TermMatch] } deriving (Monoid)
diff --git a/test/Unused/AliasesSpec.hs b/test/Unused/AliasesSpec.hs
--- a/test/Unused/AliasesSpec.hs
+++ b/test/Unused/AliasesSpec.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Unused.AliasesSpec where
 
 import Data.Monoid ((<>))
diff --git a/test/Unused/TermSearch/InternalSpec.hs b/test/Unused/TermSearch/InternalSpec.hs
--- a/test/Unused/TermSearch/InternalSpec.hs
+++ b/test/Unused/TermSearch/InternalSpec.hs
@@ -5,6 +5,7 @@
 
 import Test.Hspec
 import Unused.TermSearch.Internal
+import Unused.TermSearch.Types
 import Unused.Types
 
 main :: IO ()
@@ -14,17 +15,25 @@
 spec = parallel $ do
     describe "commandLineOptions" $ do
         it "does not use regular expressions when the term contains non-word characters" $ do
-            commandLineOptions "can_do_things?" `shouldBe` ["can_do_things?", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
-            commandLineOptions "no_way!" `shouldBe` ["no_way!", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
-            commandLineOptions "[]=" `shouldBe` ["[]=", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
-            commandLineOptions "window.globalOverride" `shouldBe` ["window.globalOverride", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+            commandLineOptions Ag "can_do_things?" `shouldBe` ["can_do_things?", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+            commandLineOptions Ag "no_way!" `shouldBe` ["no_way!", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+            commandLineOptions Ag "[]=" `shouldBe` ["[]=", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+            commandLineOptions Ag "window.globalOverride" `shouldBe` ["window.globalOverride", ".", "-Q", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
 
-        it "uses regular expression match with surrounding non-word matches for accuracy" $
-            commandLineOptions "awesome_method" `shouldBe` ["(\\W|^)awesome_method(\\W|$)", ".", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+            commandLineOptions Rg "can_do_things?" `shouldBe` ["can_do_things?", ".", "-F", "-c", "-j", "1"]
+            commandLineOptions Rg "no_way!" `shouldBe` ["no_way!", ".", "-F", "-c", "-j", "1"]
+            commandLineOptions Rg "[]=" `shouldBe` ["[]=", ".", "-F", "-c", "-j", "1"]
+            commandLineOptions Rg "window.globalOverride" `shouldBe` ["window.globalOverride", ".", "-F", "-c", "-j", "1"]
 
+        it "uses regular expression match with surrounding non-word matches for accuracy" $ do
+            commandLineOptions Ag "awesome_method" `shouldBe` ["(\\W|^)awesome_method(\\W|$)", ".", "-c", "--ackmate", "--ignore-dir", "tmp/unused"]
+            commandLineOptions Rg "awesome_method" `shouldBe` ["(\\W|^)awesome_method(\\W|$)", ".", "-c", "-j", "1"]
+
     describe "parseSearchResult" $ do
-        it "parses normal results from `ag` to a TermMatch" $
-            parseSearchResult (OriginalTerm "method_name") ":app/models/foo.rb:123" `shouldBe` (Just $ TermMatch "method_name" "app/models/foo.rb" Nothing 123)
+        it "parses normal results from `ag` to a TermMatch" $ do
+            parseSearchResult Ag (OriginalTerm "method_name") ":app/models/foo.rb:123" `shouldBe` (Just $ TermMatch "method_name" "app/models/foo.rb" Nothing 123)
+            parseSearchResult Rg (OriginalTerm "method_name") "app/models/foo.rb:123" `shouldBe` (Just $ TermMatch "method_name" "app/models/foo.rb" Nothing 123)
 
-        it "returns Nothing when it cannot parse" $
-            parseSearchResult (OriginalTerm "method_name") "" `shouldBe` Nothing
+        it "returns Nothing when it cannot parse" $ do
+            parseSearchResult Ag (OriginalTerm "method_name") "" `shouldBe` Nothing
+            parseSearchResult Rg (OriginalTerm "method_name") "" `shouldBe` Nothing
diff --git a/unused.cabal b/unused.cabal
--- a/unused.cabal
+++ b/unused.cabal
@@ -1,5 +1,5 @@
 name:                unused
-version:             0.7.0.0
+version:             0.8.0.0
 synopsis:            A command line tool to identify unused code.
 description:         Please see README.md
 homepage:            https://github.com/joshuaclayton/unused#readme
@@ -7,7 +7,7 @@
 license-file:        LICENSE
 author:              Josh Clayton
 maintainer:          sayhi@joshuaclayton.me
-copyright:           2016 Josh Clayton
+copyright:           2016-2017 Josh Clayton
 category:            CLI
 build-type:          Simple
 -- extra-source-files:
@@ -84,6 +84,7 @@
                      , file-embed
   ghc-options:         -Wall
   default-language:    Haskell2010
+  default-extensions:  OverloadedStrings
 
 executable unused
   hs-source-dirs:      app
@@ -117,6 +118,7 @@
                      , Unused.AliasesSpec
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
   default-language:    Haskell2010
+  default-extensions:  OverloadedStrings
 
 source-repository head
   type:     git
