diff --git a/README.md b/README.md
index 4fd0956..271d42e 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,8 @@ If you are using a `self-hosted` Windows runner, `GNU tar` and `zstd` are requir
 * `cache-hit` - A string value to indicate an exact match was found for the key.
   * If there's a cache hit, this will be 'true' or 'false' to indicate if there's an exact match for `key`.
   * If there's a cache miss, this will be an empty string.
+* `cache-primary-key` - Cache primary key passed in the input to use in subsequent steps of the workflow.
+* `cache-matched-key` - Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys.
 
 See [Skipping steps based on cache-hit](#skipping-steps-based-on-cache-hit) for info on using this output
 
diff --git a/__tests__/restore.test.ts b/__tests__/restore.test.ts
index 250f7ef..dac797e 100644
--- a/__tests__/restore.test.ts
+++ b/__tests__/restore.test.ts
@@ -149,7 +149,7 @@ test("restore with cache found for key", async () => {
     const infoMock = jest.spyOn(core, "info");
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -173,8 +173,10 @@ test("restore with cache found for key", async () => {
     expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
     expect(stateMock).toHaveBeenCalledTimes(2);
 
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
-    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledTimes(3);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-matched-key", key);
 
     expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
     expect(failedMock).toHaveBeenCalledTimes(0);
@@ -194,7 +196,7 @@ test("restore with cache found for restore key", async () => {
     const infoMock = jest.spyOn(core, "info");
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -218,8 +220,10 @@ test("restore with cache found for restore key", async () => {
     expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
     expect(stateMock).toHaveBeenCalledTimes(2);
 
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
-    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
+    expect(setOutputMock).toHaveBeenCalledTimes(3);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-hit", "false");
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-matched-key", restoreKey);
     expect(infoMock).toHaveBeenCalledWith(
         `Cache restored from key: ${restoreKey}`
     );
@@ -239,7 +243,7 @@ test("Fail restore when fail on cache miss is enabled and primary + restore keys
 
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -260,7 +264,8 @@ test("Fail restore when fail on cache miss is enabled and primary + restore keys
     );
 
     expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(0);
+    expect(setOutputMock).toHaveBeenCalledTimes(1);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
 
     expect(failedMock).toHaveBeenCalledWith(
         `Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ${key}`
@@ -282,7 +287,7 @@ test("restore when fail on cache miss is enabled and primary key doesn't match r
     const infoMock = jest.spyOn(core, "info");
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -306,8 +311,10 @@ test("restore when fail on cache miss is enabled and primary key doesn't match r
     expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
     expect(stateMock).toHaveBeenCalledTimes(2);
 
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
-    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
+    expect(setOutputMock).toHaveBeenCalledTimes(3);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-hit", "false");
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-matched-key", restoreKey);
 
     expect(infoMock).toHaveBeenCalledWith(
         `Cache restored from key: ${restoreKey}`
diff --git a/__tests__/restoreImpl.test.ts b/__tests__/restoreImpl.test.ts
index 16f5f72..3ddc83c 100644
--- a/__tests__/restoreImpl.test.ts
+++ b/__tests__/restoreImpl.test.ts
@@ -112,7 +112,7 @@ test("restore on GHES with AC available ", async () => {
     const infoMock = jest.spyOn(core, "info");
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -133,8 +133,10 @@ test("restore on GHES with AC available ", async () => {
     );
 
     expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
-    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledTimes(3);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-matched-key", key);
 
     expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
     expect(failedMock).toHaveBeenCalledTimes(0);
@@ -334,7 +336,7 @@ test("restore with cache found for key", async () => {
     const infoMock = jest.spyOn(core, "info");
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -355,8 +357,10 @@ test("restore with cache found for key", async () => {
     );
 
     expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
-    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledTimes(3);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-matched-key", key);
 
     expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
     expect(failedMock).toHaveBeenCalledTimes(0);
@@ -376,7 +380,7 @@ test("restore with cache found for restore key", async () => {
     const infoMock = jest.spyOn(core, "info");
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -397,8 +401,10 @@ test("restore with cache found for restore key", async () => {
     );
 
     expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
-    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
+    expect(setOutputMock).toHaveBeenCalledTimes(3);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-hit", "false");
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-matched-key", restoreKey);
     expect(infoMock).toHaveBeenCalledWith(
         `Cache restored from key: ${restoreKey}`
     );
@@ -417,7 +423,7 @@ test("restore with lookup-only set", async () => {
     const infoMock = jest.spyOn(core, "info");
     const failedMock = jest.spyOn(core, "setFailed");
     const stateMock = jest.spyOn(core, "saveState");
-    const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
+    const setOutputMock = jest.spyOn(core, "setOutput");
     const restoreCacheMock = jest
         .spyOn(cache, "restoreCache")
         .mockImplementationOnce(() => {
@@ -441,8 +447,10 @@ test("restore with lookup-only set", async () => {
     expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
     expect(stateMock).toHaveBeenCalledTimes(2);
 
-    expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
-    expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledTimes(3);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-hit", "true");
+    expect(setOutputMock).toHaveBeenCalledWith("cache-primary-key", key);
+    expect(setOutputMock).toHaveBeenCalledWith("cache-matched-key", key);
 
     expect(infoMock).toHaveBeenCalledWith(
         `Cache found and can be restored from key: ${key}`
diff --git a/__tests__/stateProvider.test.ts b/__tests__/stateProvider.test.ts
index 255b5fb..d46ee8b 100644
--- a/__tests__/stateProvider.test.ts
+++ b/__tests__/stateProvider.test.ts
@@ -54,7 +54,7 @@ test("StateProvider saves states", async () => {
     expect(cacheStateValue).toBe(cacheMatchedKey);
     expect(getStateMock).toHaveBeenCalledTimes(2);
     expect(saveStateMock).toHaveBeenCalledTimes(2);
-    expect(setOutputMock).toHaveBeenCalledTimes(0);
+    expect(setOutputMock).toHaveBeenCalledTimes(2);
 });
 
 test("NullStateProvider saves outputs", async () => {
diff --git a/action.yml b/action.yml
index 7af7458..2ab0b31 100644
--- a/action.yml
+++ b/action.yml
@@ -37,6 +37,10 @@ inputs:
 outputs:
   cache-hit:
     description: 'A boolean value to indicate an exact match was found for the primary key'
+  cache-primary-key:
+    description: 'A resolved cache key for which cache match was attempted'
+  cache-matched-key:
+    description: 'Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys'
 runs:
   using: 'node20'
   main: 'dist/restore/index.js'
diff --git a/dist/restore-only/index.js b/dist/restore-only/index.js
index c42c938..da82f3f 100644
--- a/dist/restore-only/index.js
+++ b/dist/restore-only/index.js
@@ -65114,21 +65114,22 @@ class StateProviderBase {
 class StateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.saveState;
+        this.setState = (key, value) => { core.saveState(key, value); stateToOutput(key, value); };
         this.getState = core.getState;
     }
 }
 exports.StateProvider = StateProvider;
+const stateToOutputMap = new Map([
+    [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
+    [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
+]);
+function stateToOutput(key, value) {
+    core.setOutput(stateToOutputMap.get(key), value);
+}
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.stateToOutputMap = new Map([
-            [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
-            [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
-        ]);
-        this.setState = (key, value) => {
-            core.setOutput(this.stateToOutputMap.get(key), value);
-        };
+        this.setState = stateToOutput;
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
diff --git a/dist/restore/index.js b/dist/restore/index.js
index 95f7849..9e2a513 100644
--- a/dist/restore/index.js
+++ b/dist/restore/index.js
@@ -65114,21 +65114,22 @@ class StateProviderBase {
 class StateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.saveState;
+        this.setState = (key, value) => { core.saveState(key, value); stateToOutput(key, value); };
         this.getState = core.getState;
     }
 }
 exports.StateProvider = StateProvider;
+const stateToOutputMap = new Map([
+    [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
+    [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
+]);
+function stateToOutput(key, value) {
+    core.setOutput(stateToOutputMap.get(key), value);
+}
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.stateToOutputMap = new Map([
-            [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
-            [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
-        ]);
-        this.setState = (key, value) => {
-            core.setOutput(this.stateToOutputMap.get(key), value);
-        };
+        this.setState = stateToOutput;
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
diff --git a/dist/save-only/index.js b/dist/save-only/index.js
index 1e1b222..f191eb4 100644
--- a/dist/save-only/index.js
+++ b/dist/save-only/index.js
@@ -65127,21 +65127,22 @@ class StateProviderBase {
 class StateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.saveState;
+        this.setState = (key, value) => { core.saveState(key, value); stateToOutput(key, value); };
         this.getState = core.getState;
     }
 }
 exports.StateProvider = StateProvider;
+const stateToOutputMap = new Map([
+    [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
+    [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
+]);
+function stateToOutput(key, value) {
+    core.setOutput(stateToOutputMap.get(key), value);
+}
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.stateToOutputMap = new Map([
-            [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
-            [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
-        ]);
-        this.setState = (key, value) => {
-            core.setOutput(this.stateToOutputMap.get(key), value);
-        };
+        this.setState = stateToOutput;
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
diff --git a/dist/save/index.js b/dist/save/index.js
index d288e0b..683caad 100644
--- a/dist/save/index.js
+++ b/dist/save/index.js
@@ -65127,21 +65127,22 @@ class StateProviderBase {
 class StateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.setState = core.saveState;
+        this.setState = (key, value) => { core.saveState(key, value); stateToOutput(key, value); };
         this.getState = core.getState;
     }
 }
 exports.StateProvider = StateProvider;
+const stateToOutputMap = new Map([
+    [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
+    [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
+]);
+function stateToOutput(key, value) {
+    core.setOutput(stateToOutputMap.get(key), value);
+}
 class NullStateProvider extends StateProviderBase {
     constructor() {
         super(...arguments);
-        this.stateToOutputMap = new Map([
-            [constants_1.State.CacheMatchedKey, constants_1.Outputs.CacheMatchedKey],
-            [constants_1.State.CachePrimaryKey, constants_1.Outputs.CachePrimaryKey]
-        ]);
-        this.setState = (key, value) => {
-            core.setOutput(this.stateToOutputMap.get(key), value);
-        };
+        this.setState = stateToOutput;
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         this.getState = (key) => "";
     }
diff --git a/src/stateProvider.ts b/src/stateProvider.ts
index beb41e5..f03f5ee 100644
--- a/src/stateProvider.ts
+++ b/src/stateProvider.ts
@@ -28,19 +28,22 @@ class StateProviderBase implements IStateProvider {
 }
 
 export class StateProvider extends StateProviderBase {
-    setState = core.saveState;
+    setState = (key: string, value: string) => {
+        core.saveState(key, value);
+        stateToOutput(key, value);
+    };
     getState = core.getState;
 }
 
+const stateToOutputMap = new Map<string, string>([
+    [State.CacheMatchedKey, Outputs.CacheMatchedKey],
+    [State.CachePrimaryKey, Outputs.CachePrimaryKey]
+]);
+function stateToOutput(key: string, value: string) {
+    core.setOutput(stateToOutputMap.get(key) as string, value);
+}
 export class NullStateProvider extends StateProviderBase {
-    stateToOutputMap = new Map<string, string>([
-        [State.CacheMatchedKey, Outputs.CacheMatchedKey],
-        [State.CachePrimaryKey, Outputs.CachePrimaryKey]
-    ]);
-
-    setState = (key: string, value: string) => {
-        core.setOutput(this.stateToOutputMap.get(key) as string, value);
-    };
+    setState = stateToOutput;
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     getState = (key: string) => "";
 }