diff --git a/CHANGELOG.md b/CHANGELOG.md
index c799fff..169ef89 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ The changelog for `ReactiveLists`. Also see the [releases](https://github.com/pl
 ------
 
 NEXT
+----
+0.8.3
+-----
+- Added `lightweightDiffing` option to `TableViewDriver`
+
 ----
 0.8.2
 -----
diff --git a/ReactiveLists.podspec b/ReactiveLists.podspec
index a9731e2..97a3e98 100644
--- a/ReactiveLists.podspec
+++ b/ReactiveLists.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name = "ReactiveLists"
-  s.version = "0.8.2"
+  s.version = "0.8.3"
 
   s.summary = "React-like API for UITableView and UICollectionView"
   s.homepage = "https://github.com/plangrid/ReactiveLists"
diff --git a/Sources/TableViewDriver.swift b/Sources/TableViewDriver.swift
index 76b7d22..a1cb611 100644
--- a/Sources/TableViewDriver.swift
+++ b/Sources/TableViewDriver.swift
@@ -72,6 +72,8 @@ open class TableViewDriver: NSObject {
 
     private let _automaticDiffingEnabled: Bool
 
+    private let _lightweightDiffing: Bool
+
     /// Initializes a data source that drives a `UITableView` based on a `TableViewModel`.
     ///
     /// - Parameters:
@@ -82,14 +84,19 @@ open class TableViewDriver: NSObject {
     ///   - automaticDiffingEnabled: defines whether or not this data source updates the table
     ///                              view automatically when cells/sections are moved/inserted/deleted.
     ///                              Defaults to `true`.
+    ///   - lightweightDiffing: when enabled, simply diff the count of rows rather than generating full changesets.
+    ///                         Defaults to `false`.
     public init(
         tableView: UITableView,
         tableViewModel: TableViewModel? = nil,
         shouldDeselectUponSelection: Bool = true,
-        automaticDiffingEnabled: Bool = true) {
+        automaticDiffingEnabled: Bool = true,
+        lightweightDiffing: Bool = false
+    ) {
         self._tableViewModel = tableViewModel
         self.tableView = tableView
         self._automaticDiffingEnabled = automaticDiffingEnabled
+        self._lightweightDiffing = lightweightDiffing
         self._shouldDeselectUponSelection = shouldDeselectUponSelection
         super.init()
         tableView.dataSource = self
@@ -182,40 +189,56 @@ open class TableViewDriver: NSObject {
 
         guard let newModel = newModel else { return }
 
-        if self._automaticDiffingEnabled {
+        if self._automaticDiffingEnabled, self._lightweightDiffing {
+            let old = oldModel?.sectionModels.reduce(into: 0) { $0 += $1.cellViewModels.count }
+            let new = newModel.sectionModels.reduce(into: 0) { $0 += $1.cellViewModels.count }
 
-            let visibleIndexPaths = tableView.indexPathsForVisibleRows ?? []
-            let old: [DiffableTableSectionViewModel] = oldModel?.sectionModelsForDiffing(inVisibleIndexPaths: visibleIndexPaths) ?? []
-            let changeset = StagedChangeset(
-                source: old,
-                target: newModel.sectionModelsForDiffing(inVisibleIndexPaths: visibleIndexPaths)
-            )
-            if changeset.isEmpty {
-                self._tableViewModel = newModel
+            self._tableViewModel = newModel
+            if old == new {
+                self.refreshViews(refreshContext: .contentOnly)
             } else {
-                self.tableView.reload(
-                    using: changeset,
-                    deleteSectionsAnimation: self.deletionAnimation,
-                    insertSectionsAnimation: self.insertionAnimation,
-                    reloadSectionsAnimation: self.insertionAnimation,
-                    deleteRowsAnimation: self.deletionAnimation,
-                    insertRowsAnimation: self.insertionAnimation,
-                    reloadRowsAnimation: self.insertionAnimation
-                ) {
-                    self._tableViewModel = $0.makeTableViewModel(sectionIndexTitles: oldModel?.sectionIndexTitles)
+                // We need to call reloadData here to ensure UITableView is in-sync with the data source before we start
+                // making calls to access visible cells. In the automatic diffing case, this is handled by calls to
+                // beginUpdates() endUpdates()
+                self.tableView.reloadData()
+                self.refreshViews()
+            }
+        } else {
+            if self._automaticDiffingEnabled {
+
+                let visibleIndexPaths = tableView.indexPathsForVisibleRows ?? []
+                let old: [DiffableTableSectionViewModel] = oldModel?.sectionModelsForDiffing(inVisibleIndexPaths: visibleIndexPaths) ?? []
+                let changeset = StagedChangeset(
+                    source: old,
+                    target: newModel.sectionModelsForDiffing(inVisibleIndexPaths: visibleIndexPaths)
+                )
+                if changeset.isEmpty {
+                    self._tableViewModel = newModel
+                } else {
+                    self.tableView.reload(
+                        using: changeset,
+                        deleteSectionsAnimation: self.deletionAnimation,
+                        insertSectionsAnimation: self.insertionAnimation,
+                        reloadSectionsAnimation: self.insertionAnimation,
+                        deleteRowsAnimation: self.deletionAnimation,
+                        insertRowsAnimation: self.insertionAnimation,
+                        reloadRowsAnimation: self.insertionAnimation
+                    ) {
+                        self._tableViewModel = $0.makeTableViewModel(sectionIndexTitles: oldModel?.sectionIndexTitles)
+                    }
+                    self._tableViewModel = newModel
                 }
+                // always refresh visible cells, in case some
+                // state changed that isn't captured by the diff
+                self.refreshViews(refreshContext: .contentOnly)
+            } else {
                 self._tableViewModel = newModel
+                // We need to call reloadData here to ensure UITableView is in-sync with the data source before we start
+                // making calls to access visible cells. In the automatic diffing case, this is handled by calls to
+                // beginUpdates() endUpdates()
+                self.tableView.reloadData()
+                self.refreshViews()
             }
-            // always refresh visible cells, in case some
-            // state changed that isn't captured by the diff
-            self.refreshViews(refreshContext: .contentOnly)
-        } else {
-            self._tableViewModel = newModel
-            // We need to call reloadData here to ensure UITableView is in-sync with the data source before we start
-            // making calls to access visible cells. In the automatic diffing case, this is handled by calls to
-            // beginUpdates() endUpdates()
-            self.tableView.reloadData()
-            self.refreshViews()
         }
     }