diff --git a/docs/development/configuration.md b/docs/development/configuration.md
index 54b007df01d2be1e45f131d0740600c76ef1d4fd..a238d412964bea8483ce2233bf81f506c963e13c 100644
--- a/docs/development/configuration.md
+++ b/docs/development/configuration.md
@@ -24,6 +24,9 @@ If you need an alternate location or name, set it in the environment variable `R
 For example `RENOVATE_CONFIG_FILE=myconfig.js` or `RENOVATE_CONFIG_FILE=myconfig.json` and not `RENOVATE_CONFIG_FILE=myconfig`.
 If none is provided, or the file type is invalid, Renovate will fail.
 
+If you are in an ESM repo (`"type": "module"` in `package.json`) then you must use a `.cjs` extension and set `RENOVATE_CONFIG_FILE`.
+For example `RENOVATE_CONFIG_FILE=myconfig.cjs`.
+
 Using a configuration file gives you very granular configuration options.
 For instance, you can override most settings at the global (file), repository, or package level.
 e.g. apply one set of labels for `backend/package.json` and a different set of labels for `frontend/package.json` in the same repository.
diff --git a/lib/workers/global/config/parse/__fixtures__/config.cjs b/lib/workers/global/config/parse/__fixtures__/config.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..52a85479b326bea4e999ecada5e87daedfa1fab1
--- /dev/null
+++ b/lib/workers/global/config/parse/__fixtures__/config.cjs
@@ -0,0 +1,3 @@
+module.exports = {
+  token: 'abcdefg',
+};
diff --git a/lib/workers/global/config/parse/file.spec.ts b/lib/workers/global/config/parse/file.spec.ts
index 96ad95cbeab0f50ceaa4266dea996da9c2ae1611..921a708f043279f6f80765c5afb10bb5a753d34d 100644
--- a/lib/workers/global/config/parse/file.spec.ts
+++ b/lib/workers/global/config/parse/file.spec.ts
@@ -24,6 +24,7 @@ describe('workers/global/config/parse/file', () => {
   describe('.getConfig()', () => {
     it.each([
       ['custom js config file', 'config.js'],
+      ['custom js config file', 'config.cjs'],
       ['custom js config file exporting a Promise', 'config-promise.js'],
       ['custom js config file exporting a function', 'config-function.js'],
       // The next two are different syntactic ways of expressing the same thing
diff --git a/lib/workers/global/config/parse/file.ts b/lib/workers/global/config/parse/file.ts
index f66cee56d1b494b009b933e82bf1e6fe19038e1a..693ff6467235c1b1d3ffb3f516c33e94e24bf290 100644
--- a/lib/workers/global/config/parse/file.ts
+++ b/lib/workers/global/config/parse/file.ts
@@ -25,6 +25,7 @@ export async function getParsedContent(file: string): Promise<RenovateConfig> {
         await readSystemFile(file, 'utf8'),
         file,
       ) as RenovateConfig;
+    case '.cjs':
     case '.js': {
       const tmpConfig = await import(file);
       let config = tmpConfig.default