diff --git a/news/9258.feature.rst b/news/9258.feature.rst
new file mode 100644
index 00000000000..b5907ae55a4
--- /dev/null
+++ b/news/9258.feature.rst
@@ -0,0 +1 @@
+New resolver: Add ``--no-backtracking`` option to enable failfast debugging.
diff --git a/src/pip/_internal/cli/cmdoptions.py b/src/pip/_internal/cli/cmdoptions.py
index 3543ed48bb3..3811318b4f0 100644
--- a/src/pip/_internal/cli/cmdoptions.py
+++ b/src/pip/_internal/cli/cmdoptions.py
@@ -927,6 +927,17 @@ def check_list_path_option(options):
     ),
 )  # type: Callable[..., Option]
 
+disable_backtracking = partial(
+    Option,
+    '--no-backtracking',
+    dest='disable_backtracking',
+    action='store_true',
+    default=False,
+    help='Do not attempt to backtrack to resolve package conflicts. This will '
+         'cause conflicts which may be otherwise automatically solveable to '
+         'fail fast and require manual intervention!',
+)  # type: Callable[..., Option]
+
 
 ##########
 # groups #
diff --git a/src/pip/_internal/commands/download.py b/src/pip/_internal/commands/download.py
index 7405870aefc..829ce1dc59a 100644
--- a/src/pip/_internal/commands/download.py
+++ b/src/pip/_internal/commands/download.py
@@ -56,6 +56,7 @@ def add_options(self):
         self.cmd_opts.add_option(cmdoptions.no_build_isolation())
         self.cmd_opts.add_option(cmdoptions.use_pep517())
         self.cmd_opts.add_option(cmdoptions.no_use_pep517())
+        self.cmd_opts.add_option(cmdoptions.disable_backtracking())
 
         self.cmd_opts.add_option(
             '-d', '--dest', '--destination-dir', '--destination-directory',
@@ -128,7 +129,8 @@ def run(self, options, args):
         self.trace_basic_info(finder)
 
         requirement_set = resolver.resolve(
-            reqs, check_supported_wheels=True
+            reqs, check_supported_wheels=True,
+            should_backtrack=not options.disable_backtracking
         )
 
         downloaded = []  # type: List[str]
diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py
index a4e10f260a2..3dc2a5cb186 100644
--- a/src/pip/_internal/commands/install.py
+++ b/src/pip/_internal/commands/install.py
@@ -216,6 +216,7 @@ def add_options(self):
         self.cmd_opts.add_option(cmdoptions.prefer_binary())
         self.cmd_opts.add_option(cmdoptions.require_hashes())
         self.cmd_opts.add_option(cmdoptions.progress_bar())
+        self.cmd_opts.add_option(cmdoptions.disable_backtracking())
 
         index_opts = cmdoptions.make_option_group(
             cmdoptions.index_group,
@@ -318,7 +319,8 @@ def run(self, options, args):
             self.trace_basic_info(finder)
 
             requirement_set = resolver.resolve(
-                reqs, check_supported_wheels=not options.target_dir
+                reqs, check_supported_wheels=not options.target_dir,
+                should_backtrack=not options.disable_backtracking
             )
 
             try:
diff --git a/src/pip/_internal/commands/wheel.py b/src/pip/_internal/commands/wheel.py
index 39fd2bf8128..1c125c1ed58 100644
--- a/src/pip/_internal/commands/wheel.py
+++ b/src/pip/_internal/commands/wheel.py
@@ -80,6 +80,7 @@ def add_options(self):
         self.cmd_opts.add_option(cmdoptions.no_deps())
         self.cmd_opts.add_option(cmdoptions.build_dir())
         self.cmd_opts.add_option(cmdoptions.progress_bar())
+        self.cmd_opts.add_option(cmdoptions.disable_backtracking())
 
         self.cmd_opts.add_option(
             '--global-option',
@@ -152,7 +153,8 @@ def run(self, options, args):
         self.trace_basic_info(finder)
 
         requirement_set = resolver.resolve(
-            reqs, check_supported_wheels=True
+            reqs, check_supported_wheels=True,
+            should_backtrack=not options.disable_backtracking
         )
 
         reqs_to_build = []  # type: List[InstallRequirement]
diff --git a/src/pip/_internal/resolution/base.py b/src/pip/_internal/resolution/base.py
index 6d50555e531..b570d9e7a63 100644
--- a/src/pip/_internal/resolution/base.py
+++ b/src/pip/_internal/resolution/base.py
@@ -12,8 +12,8 @@
 
 
 class BaseResolver(object):
-    def resolve(self, root_reqs, check_supported_wheels):
-        # type: (List[InstallRequirement], bool) -> RequirementSet
+    def resolve(self, root_reqs, check_supported_wheels, should_backtrack):
+        # type: (List[InstallRequirement], bool, bool) -> RequirementSet
         raise NotImplementedError()
 
     def get_installation_order(self, req_set):
diff --git a/src/pip/_internal/resolution/legacy/resolver.py b/src/pip/_internal/resolution/legacy/resolver.py
index d0fc1a7b316..12519a72d24 100644
--- a/src/pip/_internal/resolution/legacy/resolver.py
+++ b/src/pip/_internal/resolution/legacy/resolver.py
@@ -149,8 +149,9 @@ def __init__(
         self._discovered_dependencies = \
             defaultdict(list)  # type: DiscoveredDependencies
 
-    def resolve(self, root_reqs, check_supported_wheels):
-        # type: (List[InstallRequirement], bool) -> RequirementSet
+    def resolve(self, root_reqs, check_supported_wheels, should_backtrack):
+        # type: (List[InstallRequirement], bool, bool) -> RequirementSet
+        # pylint: disable=unused-argument
         """Resolve what operations need to be done
 
         As a side-effect of this method, the packages (and their dependencies)
diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py
index 30b860f6c48..a3cc7abb4b3 100644
--- a/src/pip/_internal/resolution/resolvelib/resolver.py
+++ b/src/pip/_internal/resolution/resolvelib/resolver.py
@@ -75,8 +75,8 @@ def __init__(
         self.upgrade_strategy = upgrade_strategy
         self._result = None  # type: Optional[Result]
 
-    def resolve(self, root_reqs, check_supported_wheels):
-        # type: (List[InstallRequirement], bool) -> RequirementSet
+    def resolve(self, root_reqs, check_supported_wheels, should_backtrack):
+        # type: (List[InstallRequirement], bool, bool) -> RequirementSet
 
         constraints = {}  # type: Dict[str, Constraint]
         user_requested = set()  # type: Set[str]
@@ -120,6 +120,7 @@ def resolve(self, root_reqs, check_supported_wheels):
             try_to_avoid_resolution_too_deep = 2000000
             self._result = resolver.resolve(
                 requirements, max_rounds=try_to_avoid_resolution_too_deep,
+                should_backtrack=should_backtrack,
             )
 
         except ResolutionImpossible as e:
diff --git a/src/pip/_vendor/resolvelib/__init__.py b/src/pip/_vendor/resolvelib/__init__.py
index 5a400f23ed1..12f59c66500 100644
--- a/src/pip/_vendor/resolvelib/__init__.py
+++ b/src/pip/_vendor/resolvelib/__init__.py
@@ -11,7 +11,7 @@
     "ResolutionTooDeep",
 ]
 
-__version__ = "0.5.3"
+__version__ = "0.5.4.dev0"
 
 
 from .providers import AbstractProvider, AbstractResolver
diff --git a/src/pip/_vendor/resolvelib/resolvers.py b/src/pip/_vendor/resolvelib/resolvers.py
index acf0f8a6b43..3ddb6939272 100644
--- a/src/pip/_vendor/resolvelib/resolvers.py
+++ b/src/pip/_vendor/resolvelib/resolvers.py
@@ -297,7 +297,7 @@ def _backtrack(self):
         # No way to backtrack anymore.
         return False
 
-    def resolve(self, requirements, max_rounds):
+    def resolve(self, requirements, max_rounds, should_backtrack):
         if self._states:
             raise RuntimeError("already resolved")
 
@@ -341,7 +341,7 @@ def resolve(self, requirements, max_rounds):
             if failure_causes:
                 # Backtrack if pinning fails. The backtrack process puts us in
                 # an unpinned state, so we can work on it in the next round.
-                success = self._backtrack()
+                success = self._backtrack() if should_backtrack else False
 
                 # Dead ends everywhere. Give up.
                 if not success:
@@ -413,7 +413,7 @@ class Resolver(AbstractResolver):
 
     base_exception = ResolverException
 
-    def resolve(self, requirements, max_rounds=100):
+    def resolve(self, requirements, max_rounds=100, should_backtrack=True):
         """Take a collection of constraints, spit out the resolution result.
 
         The return value is a representation to the final resolution result. It
@@ -442,5 +442,9 @@ def resolve(self, requirements, max_rounds=100):
             `max_rounds` argument.
         """
         resolution = Resolution(self.provider, self.reporter)
-        state = resolution.resolve(requirements, max_rounds=max_rounds)
+        state = resolution.resolve(
+            requirements,
+            max_rounds=max_rounds,
+            should_backtrack=should_backtrack,
+        )
         return _build_result(state)
diff --git a/src/pip/_vendor/vendor.txt b/src/pip/_vendor/vendor.txt
index c7bc37c16c4..24738dff8a1 100644
--- a/src/pip/_vendor/vendor.txt
+++ b/src/pip/_vendor/vendor.txt
@@ -16,7 +16,7 @@ requests==2.25.0
     chardet==3.0.4
     idna==2.10
     urllib3==1.26.2
-resolvelib==0.5.3
+git+https://github.com/thekevjames/resolvelib.git@add-no-backtracking-option
 retrying==1.3.3
 setuptools==44.0.0
 six==1.15.0
diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py
index f9a807bca79..55aaeadd331 100644
--- a/tests/functional/test_install.py
+++ b/tests/functional/test_install.py
@@ -1726,6 +1726,55 @@ def test_install_conflict_warning_can_be_suppressed(script, data):
     assert "Successfully installed pkgB-2.0" in result2.stdout, str(result2)
 
 
+def test_install_incompatiblity_can_failfast(script, data):
+    # Build the following package dependency graph, which is impossible to
+    # resolve:
+    #
+    #             /- pkgB == 1.0 -> pkgD == 1.0
+    #            / - pkgB == 1.1 -> pkgD == 1.0
+    # pkgA==1.0 -
+    #            \ - pkgC == 1.0 -> pkgD == 1.1
+    #             \- pkgC == 1.1 -> pkgD == 1.1
+    pkgA_path = create_basic_wheel_for_package(
+        script,
+        name='pkgA', version='1.0', depends=[
+            'pkgb > 1.0, < 2.0',
+            'pkgc > 1.0, < 2.0',
+        ],
+    )
+    for minor in {0, 1}:
+        create_basic_wheel_for_package(
+            script,
+            name='pkgB', version='1.%s' % minor,
+            depends=['pkgd == 1.0'],
+        )
+        create_basic_wheel_for_package(
+            script,
+            name='pkgC', version='1.%s' % minor,
+            depends=['pkgd == 1.1'],
+        )
+        create_basic_wheel_for_package(
+            script,
+            name='pkgD', version='1.%s' % minor,
+        )
+
+    # Installing normally should run backtracking...
+    result1 = script.pip(
+        'install', '--no-index', '--find-links', script.scratch_path,
+        pkgA_path, expect_error=True
+    )
+    assert 'pip is looking at multiple versions of pkg' in result1.stdout
+    assert 'ResolutionImpossible' in result1.stderr
+
+    # ...but the ``--no-backtracking`` flag will prevent this behaviour
+    result2 = script.pip(
+        'install', '--no-index', '--find-links', script.scratch_path,
+        '--no-backtracking', pkgA_path, expect_error=True
+    )
+    assert 'pip is looking at multiple versions of pkg' not in result2.stdout
+    assert 'ResolutionImpossible' in result2.stderr
+
+
 def test_target_install_ignores_distutils_config_install_prefix(script):
     prefix = script.scratch_path / 'prefix'
     distutils_config = Path(os.path.expanduser('~'),
diff --git a/tests/unit/test_req.py b/tests/unit/test_req.py
index e168a3cc164..ddfd4490639 100644
--- a/tests/unit/test_req.py
+++ b/tests/unit/test_req.py
@@ -121,6 +121,7 @@ def test_no_reuse_existing_build_dir(self, data):
                 resolver.resolve,
                 reqset.all_requirements,
                 True,
+                True,
             )
 
     # TODO: Update test when Python 2.7 is dropped.
@@ -137,7 +138,7 @@ def test_environment_marker_extras(self, data):
         reqset.add_requirement(req)
         finder = make_test_finder(find_links=[data.find_links])
         with self._basic_resolver(finder) as resolver:
-            reqset = resolver.resolve(reqset.all_requirements, True)
+            reqset = resolver.resolve(reqset.all_requirements, True, True)
         # This is hacky but does test both case in py2 and py3
         if sys.version_info[:2] == (2, 7):
             assert reqset.has_requirement('simple')
@@ -165,6 +166,7 @@ def test_missing_hash_with_require_hashes(self, data):
                 resolver.resolve,
                 reqset.all_requirements,
                 True,
+                True,
             )
 
     def test_missing_hash_with_require_hashes_in_reqs_file(self, data, tmpdir):
@@ -217,6 +219,7 @@ def test_unsupported_hashes(self, data):
                 resolver.resolve,
                 reqset.all_requirements,
                 True,
+                True,
             )
 
     def test_unpinned_hash_checking(self, data):
@@ -246,6 +249,7 @@ def test_unpinned_hash_checking(self, data):
                 resolver.resolve,
                 reqset.all_requirements,
                 True,
+                True,
             )
 
     def test_hash_mismatch(self, data):
@@ -268,6 +272,7 @@ def test_hash_mismatch(self, data):
                 resolver.resolve,
                 reqset.all_requirements,
                 True,
+                True,
             )
 
     def test_unhashed_deps_on_require_hashes(self, data):
@@ -291,6 +296,7 @@ def test_unhashed_deps_on_require_hashes(self, data):
                 resolver.resolve,
                 reqset.all_requirements,
                 True,
+                True,
             )
 
     def test_hashed_deps_on_require_hashes(self):