diff --git a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap
index da1ab355e9456b21eced871c467a164f5462bd84..a2c73308b47f9d8e16d54c290ba779bba92254b0 100644
--- a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap
+++ b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap
@@ -120,7 +120,7 @@ Array [
     },
   },
   Object {
-    "cmd": "docker run --rm --name=renovate_go --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go get -d ./...\\"",
+    "cmd": "docker run --rm --name=renovate_go --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go get -d ./... && go mod tidy\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -140,6 +140,17 @@ Array [
       "timeout": 900000,
     },
   },
+]
+`;
+
+exports[`.updateArtifacts() supports docker mode without credentials 1`] = `
+Array [
+  Object {
+    "cmd": "docker pull renovate/go:latest",
+    "options": Object {
+      "encoding": "utf-8",
+    },
+  },
   Object {
     "cmd": "docker ps --filter name=renovate_go -aq",
     "options": Object {
@@ -147,7 +158,7 @@ Array [
     },
   },
   Object {
-    "cmd": "docker run --rm --name=renovate_go --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go mod tidy\\"",
+    "cmd": "docker run --rm --name=renovate_go --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"go get -d ./...\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -170,22 +181,57 @@ Array [
 ]
 `;
 
-exports[`.updateArtifacts() supports docker mode without credentials 1`] = `
+exports[`.updateArtifacts() supports global mode 1`] = `
 Array [
   Object {
-    "cmd": "docker pull renovate/go:latest",
+    "cmd": "go get -d ./...",
     "options": Object {
+      "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
+      "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
+        "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
+        "HOME": "/home/user",
+        "HTTPS_PROXY": "https://example.com",
+        "HTTP_PROXY": "http://example.com",
+        "LANG": "en_US.UTF-8",
+        "LC_ALL": "en_US",
+        "NO_PROXY": "localhost",
+        "PATH": "/tmp/path",
+      },
+      "timeout": 900000,
     },
   },
+]
+`;
+
+exports[`.updateArtifacts() supports vendor directory update 1`] = `
+Array [
   Object {
-    "cmd": "docker ps --filter name=renovate_go -aq",
+    "cmd": "go get -d ./...",
     "options": Object {
+      "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
+      "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
+        "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
+        "HOME": "/home/user",
+        "HTTPS_PROXY": "https://example.com",
+        "HTTP_PROXY": "http://example.com",
+        "LANG": "en_US.UTF-8",
+        "LC_ALL": "en_US",
+        "NO_PROXY": "localhost",
+        "PATH": "/tmp/path",
+      },
+      "timeout": 900000,
     },
   },
   Object {
-    "cmd": "docker run --rm --name=renovate_go --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"go get -d ./...\\"",
+    "cmd": "go mod tidy",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -205,13 +251,29 @@ Array [
       "timeout": 900000,
     },
   },
-]
-`;
-
-exports[`.updateArtifacts() supports global mode 1`] = `
-Array [
   Object {
-    "cmd": "go get -d ./...",
+    "cmd": "go mod vendor",
+    "options": Object {
+      "cwd": "/tmp/github/some/repo",
+      "encoding": "utf-8",
+      "env": Object {
+        "CGO_ENABLED": "1",
+        "GONOSUMDB": "1",
+        "GOPATH": "/tmp/renovate/cache/others/go",
+        "GOPROXY": "proxy.example.com",
+        "HOME": "/home/user",
+        "HTTPS_PROXY": "https://example.com",
+        "HTTP_PROXY": "http://example.com",
+        "LANG": "en_US.UTF-8",
+        "LC_ALL": "en_US",
+        "NO_PROXY": "localhost",
+        "PATH": "/tmp/path",
+      },
+      "timeout": 900000,
+    },
+  },
+  Object {
+    "cmd": "go mod tidy",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
diff --git a/lib/manager/gomod/artifacts.spec.ts b/lib/manager/gomod/artifacts.spec.ts
index 255a15ccc8d87dc8e404dad1ed6bfa7697723be0..0e632f61d27251ef10cd225f0ea304e89029dc8e 100644
--- a/lib/manager/gomod/artifacts.spec.ts
+++ b/lib/manager/gomod/artifacts.spec.ts
@@ -73,6 +73,7 @@ describe('.updateArtifacts()', () => {
   });
   it('returns null if unchanged', async () => {
     fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     const execSnapshots = mockExecAll(exec);
     git.getRepoStatus.mockResolvedValueOnce({
       modified: [],
@@ -89,11 +90,12 @@ describe('.updateArtifacts()', () => {
   });
   it('returns updated go.sum', async () => {
     fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     const execSnapshots = mockExecAll(exec);
     git.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
     } as StatusResult);
-    fs.readFile.mockReturnValueOnce('New go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('New go.sum' as any);
     expect(
       await gomod.updateArtifacts({
         packageFileName: 'go.mod',
@@ -104,15 +106,52 @@ describe('.updateArtifacts()', () => {
     ).not.toBeNull();
     expect(execSnapshots).toMatchSnapshot();
   });
+  it('supports vendor directory update', async () => {
+    const foo = join('vendor/github.com/foo/foo/go.mod');
+    const bar = join('vendor/github.com/bar/bar/go.mod');
+    const baz = join('vendor/github.com/baz/baz/go.mod');
+
+    fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('modules.txt content' as any); // vendor modules filename
+    const execSnapshots = mockExecAll(exec);
+    git.getRepoStatus.mockResolvedValueOnce({
+      modified: ['go.sum', foo],
+      not_added: [bar],
+      deleted: [baz],
+    } as StatusResult);
+    fs.readFile.mockResolvedValueOnce('New go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('Foo go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('Bar go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('New go.mod' as any);
+    const res = await gomod.updateArtifacts({
+      packageFileName: 'go.mod',
+      updatedDeps: [],
+      newPackageFileContent: gomod1,
+      config: {
+        ...config,
+        postUpdateOptions: ['gomodTidy'],
+      },
+    });
+    expect(res).not.toBeNull();
+    expect(res?.map(({ file }) => file)).toEqual([
+      { contents: 'New go.sum', name: 'go.sum' },
+      { contents: 'Foo go.sum', name: foo },
+      { contents: 'Bar go.sum', name: bar },
+      { contents: baz, name: '|delete|' },
+      { contents: 'New go.mod', name: 'go.mod' },
+    ]);
+    expect(execSnapshots).toMatchSnapshot();
+  });
   it('supports docker mode without credentials', async () => {
     jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
     await setUtilConfig({ ...config, binarySource: BinarySource.Docker });
     fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     const execSnapshots = mockExecAll(exec);
     git.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
     } as StatusResult);
-    fs.readFile.mockReturnValueOnce('New go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('New go.sum' as any);
     expect(
       await gomod.updateArtifacts({
         packageFileName: 'go.mod',
@@ -128,11 +167,12 @@ describe('.updateArtifacts()', () => {
   });
   it('supports global mode', async () => {
     fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     const execSnapshots = mockExecAll(exec);
     git.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
     } as StatusResult);
-    fs.readFile.mockReturnValueOnce('New go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('New go.sum' as any);
     expect(
       await gomod.updateArtifacts({
         packageFileName: 'go.mod',
@@ -153,11 +193,12 @@ describe('.updateArtifacts()', () => {
       token: 'some-token',
     });
     fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     const execSnapshots = mockExecAll(exec);
     git.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
     } as StatusResult);
-    fs.readFile.mockReturnValueOnce('New go.sum' as any);
+    fs.readFile.mockResolvedValueOnce('New go.sum' as any);
     expect(
       await gomod.updateArtifacts({
         packageFileName: 'go.mod',
@@ -178,14 +219,15 @@ describe('.updateArtifacts()', () => {
       token: 'some-token',
     });
     fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     const execSnapshots = mockExecAll(exec);
     git.getRepoStatus.mockResolvedValueOnce({
       modified: ['go.sum'],
     } as StatusResult);
     fs.readFile.mockResolvedValueOnce('New go.sum 1' as any);
-    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     fs.readFile.mockResolvedValueOnce('New go.sum 2' as any);
     fs.readFile.mockResolvedValueOnce('New go.sum 3' as any);
+    fs.readFile.mockResolvedValueOnce('New go.mod' as any);
     try {
       global.appMode = true;
       expect(
@@ -208,6 +250,7 @@ describe('.updateArtifacts()', () => {
   it('catches errors', async () => {
     const execSnapshots = mockExecAll(exec);
     fs.readFile.mockResolvedValueOnce('Current go.sum' as any);
+    fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename
     fs.outputFile.mockImplementationOnce(() => {
       throw new Error('This update totally doesnt work');
     });
diff --git a/lib/manager/gomod/artifacts.ts b/lib/manager/gomod/artifacts.ts
index 092c19725f8c808e4eb16353e3a9ab1c70e304b0..8c0bddc01ccb53f1514cf8ca0648ff59241b3561 100644
--- a/lib/manager/gomod/artifacts.ts
+++ b/lib/manager/gomod/artifacts.ts
@@ -44,6 +44,11 @@ export async function updateArtifacts({
     logger.debug('No go.sum found');
     return null;
   }
+
+  const vendorDir = join(dirname(goModFileName), 'vendor/');
+  const vendorModulesFileName = join(vendorDir, 'modules.txt');
+  const useVendor = (await readLocalFile(vendorModulesFileName)) !== null;
+
   try {
     const massagedGoMod = newGoModContent.replace(
       /\n(replace\s+[^\s]+\s+=>\s+\.\.\/.*)/g,
@@ -53,6 +58,7 @@ export async function updateArtifacts({
       logger.debug('Removed some relative replace statements from go.mod');
     }
     await writeLocalFile(goModFileName, massagedGoMod);
+
     const cmd = 'go';
     const execOptions: ExecOptions = {
       cwdFile: goModFileName,
@@ -71,47 +77,44 @@ export async function updateArtifacts({
       },
     };
     let args = 'get -d ./...';
-    logger.debug({ cmd, args }, 'go get command');
-    await exec(`${cmd} ${args}`, execOptions);
-    if (
-      config.postUpdateOptions &&
-      config.postUpdateOptions.includes('gomodTidy')
-    ) {
+    logger.debug({ cmd, args }, 'go get command included');
+    const execCommands = [`${cmd} ${args}`];
+
+    if (config.postUpdateOptions?.includes('gomodTidy')) {
       args = 'mod tidy';
-      logger.debug({ cmd, args }, 'go mod tidy command');
-      await exec(`${cmd} ${args}`, execOptions);
+      logger.debug({ cmd, args }, 'go mod tidy command included');
+      execCommands.push(`${cmd} ${args}`);
     }
-    const res = [];
-    let status = await getRepoStatus();
+
+    if (useVendor) {
+      args = 'mod vendor';
+      logger.debug({ cmd, args }, 'go mod vendor command included');
+      execCommands.push(`${cmd} ${args}`);
+      if (config.postUpdateOptions?.includes('gomodTidy')) {
+        args = 'mod tidy';
+        logger.debug({ cmd, args }, 'go mod tidy command included');
+        execCommands.push(`${cmd} ${args}`);
+      }
+    }
+
+    await exec(execCommands, execOptions);
+
+    const status = await getRepoStatus();
     if (!status.modified.includes(sumFileName)) {
       return null;
     }
+
     logger.debug('Returning updated go.sum');
-    res.push({
-      file: {
-        name: sumFileName,
-        contents: await readLocalFile(sumFileName),
+    const res: UpdateArtifactsResult[] = [
+      {
+        file: {
+          name: sumFileName,
+          contents: await readLocalFile(sumFileName),
+        },
       },
-    });
-    const vendorDir = join(dirname(goModFileName), 'vendor/');
-    const vendorModulesFileName = join(vendorDir, 'modules.txt');
-    // istanbul ignore if
-    if (await readLocalFile(vendorModulesFileName)) {
-      args = 'mod vendor';
-      logger.debug({ cmd, args }, 'go mod vendor command');
-      await exec(`${cmd} ${args}`, execOptions);
-      if (
-        config.postUpdateOptions &&
-        config.postUpdateOptions.includes('gomodTidy')
-      ) {
-        args = 'mod tidy';
-        if (cmd.includes('.insteadOf')) {
-          args += '"';
-        }
-        logger.debug({ cmd, args }, 'go mod tidy command');
-        await exec(`${cmd} ${args}`, execOptions);
-      }
-      status = await getRepoStatus();
+    ];
+
+    if (useVendor) {
       for (const f of status.modified.concat(status.not_added)) {
         if (f.startsWith(vendorDir)) {
           res.push({
@@ -131,6 +134,7 @@ export async function updateArtifacts({
         });
       }
     }
+
     const finalGoModContent = (
       await readLocalFile(goModFileName, 'utf8')
     ).replace(/\/\/ renovate-replace /g, '');