diff --git a/__tests__/actionUtils.test.ts b/__tests__/actionUtils.test.ts
index a6dc291..0a11d1f 100644
--- a/__tests__/actionUtils.test.ts
+++ b/__tests__/actionUtils.test.ts
@@ -194,3 +194,13 @@ test("getInputAsArray handles empty lines correctly", () => {
     testUtils.setInput("foo", "\n\nbar\n\nbaz\n\n");
     expect(actionUtils.getInputAsArray("foo")).toEqual(["bar", "baz"]);
 });
+
+test("getInputAsBoolean returns true if the value is set to 'true'", () => {
+    testUtils.setInput("foo", "true");
+    expect(actionUtils.getInputAsBoolean("foo")).toEqual(true);
+});
+
+test("getInputAsBoolean returns false if the value is set to anything else", () => {
+    testUtils.setInput("foo", "false");
+    expect(actionUtils.getInputAsBoolean("foo")).toEqual(false);
+});
diff --git a/__tests__/save.test.ts b/__tests__/save.test.ts
index 943a2bd..3c55645 100644
--- a/__tests__/save.test.ts
+++ b/__tests__/save.test.ts
@@ -118,6 +118,41 @@ test("save with exact match returns early", async () => {
     expect(failedMock).toHaveBeenCalledTimes(0);
 });
 
+test("save with exact match updates when configured", async () => {
+    const failedMock = jest.spyOn(core, "setFailed");
+
+    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
+    const savedCacheKey = primaryKey;
+
+    jest.spyOn(core, "getState")
+        // Cache Entry State
+        .mockImplementationOnce(() => {
+            return savedCacheKey;
+        })
+        // Cache Key State
+        .mockImplementationOnce(() => {
+            return primaryKey;
+        });
+
+    const inputPath = "node_modules";
+    testUtils.setInput(Inputs.Path, inputPath);
+    testUtils.setInput(Inputs.Update, "true");
+
+    const cacheId = 4;
+    const saveCacheMock = jest
+        .spyOn(cache, "saveCache")
+        .mockImplementationOnce(() => {
+            return Promise.resolve(cacheId);
+        });
+
+    await run();
+
+    expect(saveCacheMock).toHaveBeenCalledTimes(1);
+    expect(saveCacheMock).toHaveBeenCalledWith([inputPath], primaryKey);
+
+    expect(failedMock).toHaveBeenCalledTimes(0);
+});
+
 test("save with missing input outputs warning", async () => {
     const logWarningMock = jest.spyOn(actionUtils, "logWarning");
     const failedMock = jest.spyOn(core, "setFailed");
diff --git a/action.yml b/action.yml
index e50c38b..47fa26a 100644
--- a/action.yml
+++ b/action.yml
@@ -11,6 +11,9 @@ inputs:
   restore-keys:
     description: 'An ordered list of keys to use for restoring the cache if no cache hit occurred for key'
     required: false
+  update:
+    description: 'If true, the cache will be updated if the key already exists'
+    required: false
 outputs:
   cache-hit:
     description: 'A boolean value to indicate an exact match was found for the primary key'
diff --git a/src/constants.ts b/src/constants.ts
index a190e00..b32968e 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,7 +1,8 @@
 export enum Inputs {
     Key = "key",
     Path = "path",
-    RestoreKeys = "restore-keys"
+    RestoreKeys = "restore-keys",
+    Update = "update"
 }
 
 export enum Outputs {
diff --git a/src/save.ts b/src/save.ts
index 80b656c..6897a57 100644
--- a/src/save.ts
+++ b/src/save.ts
@@ -16,15 +16,17 @@ async function run(): Promise<void> {
         }
 
         const state = utils.getCacheState();
-
-        // Inputs are re-evaluted before the post action, so we want the original key used for restore
+        // Inputs are re-evaluated before the post action, so we want the original key used for restore
         const primaryKey = core.getState(State.CachePrimaryKey);
         if (!primaryKey) {
             utils.logWarning(`Error retrieving key from state.`);
             return;
         }
 
-        if (utils.isExactKeyMatch(primaryKey, state)) {
+        if (
+            utils.isExactKeyMatch(primaryKey, state) &&
+            !utils.getInputAsBoolean(Inputs.Update)
+        ) {
             core.info(
                 `Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
             );
diff --git a/src/utils/actionUtils.ts b/src/utils/actionUtils.ts
index 26bb8c1..256b8e6 100644
--- a/src/utils/actionUtils.ts
+++ b/src/utils/actionUtils.ts
@@ -56,3 +56,10 @@ export function getInputAsArray(
         .map(s => s.trim())
         .filter(x => x !== "");
 }
+
+export function getInputAsBoolean(
+    name: string,
+    options?: core.InputOptions
+): boolean {
+    return core.getInput(name, options) === "true";
+}