diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,8 @@
-## [_Unreleased_](https://github.com/freckle/stackctl/compare/v1.7.0.0...main)
+## [_Unreleased_](https://github.com/freckle/stackctl/compare/v1.7.1.0...main)
+
+## [v1.7.1.0](https://github.com/freckle/stackctl/compare/v1.7.0.0...v1.7.1.0)
+
+- Add `withAssumedRole`, deprecate `assumeRole`
 
 ## [v1.7.0.0](https://github.com/freckle/stackctl/compare/v1.6.1.2...v1.7.0.0)
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -76,6 +76,33 @@
 The man pages are also available [online](https://freckle.github.io/stackctl/),
 but contain documentation as of `main`, and not your installed version.
 
+## Comparison to AWS CloudFormation Git Sync
+
+[AWS CloudFormation Git Sync][aws-git-sync] was recently released by AWS. It
+allows you to link a repository on GitHub to a CloudFormation Stack. The
+repository contains a "deployment file" that defines a `template-file-path`,
+`parameters`, and `tags` -- effectively, a Stack Specification.
+
+When AWS notices updates to the deployment or template file land on a defined
+branch, it updates the configured Stack accordingly, emitting events to SNS as
+it does.
+
+This is great for simple use-cases, and we fully expect they'll improve and
+extend it such that it obviates Stackctl one day. In the meantime, there are
+currently the following limitations when compared to Stackctl:
+
+1. A repository can only target a single account and region
+1. There is no changeset flow amenable to previewing changes via PRs. You update
+   the file(s) on `main` and it syncs, that's it. If you're using a PR, you have
+   only linting and human review as possible pre-deployment steps.
+1. There is no way to specify description, capabilities, or dependencies
+1. As of 12/23, there seemed to be some bugs, and the setup installs a managed
+   event bridge that "phones home", sending events about your updates to some
+   other AWS account ([source][first-look-blog])
+
+[aws-git-sync]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/git-sync.html
+[first-look-blog]: https://medium.com/@mattgillard/first-look-git-sync-for-cloudformation-stacks-9e2f39c311ac
+
 ## Relationship to CloudGenesis
 
 [CloudGenesis][] is a project that also takes a directory of Stack
diff --git a/src/Stackctl/AWS/Core.hs b/src/Stackctl/AWS/Core.hs
--- a/src/Stackctl/AWS/Core.hs
+++ b/src/Stackctl/AWS/Core.hs
@@ -9,7 +9,7 @@
     -- * "Control.Monad.AWS" extensions
   , simple
   , discover
-  , assumeRole
+  , withAssumedRole
 
     -- * Error-handling
   , handlingServiceError
@@ -22,6 +22,9 @@
   , Region (..)
   , FromText (..)
   , ToText (..)
+
+    -- * Deprecated
+  , assumeRole
   ) where
 
 import Stackctl.Prelude
@@ -29,6 +32,7 @@
 import Amazonka
   ( AWSRequest
   , AWSResponse
+  , Env' (auth)
   , Region
   , ServiceError
   , serviceError_code
@@ -38,6 +42,7 @@
   , _ServiceError
   )
 import qualified Amazonka
+import Amazonka.Auth.Background (fetchAuthInBackground)
 import Amazonka.Auth.Keys (fromSession)
 import Amazonka.Data.Text (FromText (..), ToText (..))
 import qualified Amazonka.Env as Amazonka
@@ -87,6 +92,11 @@
 
   maybe (throwString err) pure $ post resp
 
+-- | Use 'withAssumedRole' instead
+--
+-- This function is like 'withAssumedRole' except it doesn't spawn a background
+-- thread to keep credentials refreshed. You may encounter expired credentials
+-- if the block used under 'assumeRole' goes for long enough.
 assumeRole
   :: (MonadIO m, MonadAWS m)
   => Text
@@ -111,6 +121,30 @@
     pure $ fromSession accessKeyId secretAccessKey sessionToken
 
   localEnv assumeEnv f
+{-# DEPRECATED assumeRole "Use withAssumedRole instead" #-}
+
+-- | Assume a role using the @sts:AssumeRole@ API and run an action
+withAssumedRole
+  :: (MonadUnliftIO m, MonadAWS m)
+  => Text
+  -- ^ Role ARN
+  -> Text
+  -- ^ Role session name
+  -> m a
+  -- ^ Action to run as the assumed role
+  -> m a
+withAssumedRole roleArn roleSessionName f = do
+  keys <- withRunInIO $ \runInIO -> do
+    let getCredentials = do
+          resp <-
+            runInIO
+              $ send
+              $ newAssumeRole roleArn roleSessionName
+          pure $ resp ^. assumeRoleResponse_credentials
+
+    fetchAuthInBackground getCredentials
+
+  localEnv (\env -> env {auth = Identity keys}) f
 
 newtype AccountId = AccountId
   { unAccountId :: Text
diff --git a/stackctl.cabal b/stackctl.cabal
--- a/stackctl.cabal
+++ b/stackctl.cabal
@@ -1,6 +1,6 @@
 cabal-version:   1.18
 name:            stackctl
-version:         1.7.0.0
+version:         1.7.1.0
 license:         MIT
 license-file:    LICENSE
 copyright:       2022 Renaissance Learning Inc
