diff --git a/src/android/app/src/main/jni/system_save_game.cpp b/src/android/app/src/main/jni/system_save_game.cpp
index 003ad1b63..bdf97c8bc 100644
--- a/src/android/app/src/main/jni/system_save_game.cpp
+++ b/src/android/app/src/main/jni/system_save_game.cpp
@@ -19,11 +19,7 @@ void Java_org_citra_citra_1emu_utils_SystemSaveGame_save([[maybe_unused]] JNIEnv
 
 void Java_org_citra_citra_1emu_utils_SystemSaveGame_load([[maybe_unused]] JNIEnv* env,
                                                          [[maybe_unused]] jobject obj) {
-    if (Core::System::GetInstance().IsPoweredOn()) {
-        cfg = Service::CFG::GetModule(Core::System::GetInstance());
-    } else {
-        cfg = std::make_shared<Service::CFG::Module>();
-    }
+    cfg = Service::CFG::GetModule(Core::System::GetInstance());
 }
 
 jboolean Java_org_citra_citra_1emu_utils_SystemSaveGame_getIsSystemSetupNeeded(
diff --git a/src/citra_qt/configuration/configure_system.cpp b/src/citra_qt/configuration/configure_system.cpp
index f0ae442d6..ebf2eb6dd 100644
--- a/src/citra_qt/configuration/configure_system.cpp
+++ b/src/citra_qt/configuration/configure_system.cpp
@@ -293,16 +293,11 @@ void ConfigureSystem::SetConfiguration() {
     QTime time = QTime::fromMSecsSinceStartOfDay(static_cast<int>(time_offset * 1000));
     ui->edit_init_time_offset_time->setTime(time);
 
-    if (!enabled) {
-        cfg = Service::CFG::GetModule(system);
-        ASSERT_MSG(cfg, "CFG Module missing!");
-        ReadSystemSettings();
-        ui->group_system_settings->setEnabled(false);
-    } else {
-        // This tab is enabled only when game is not running (i.e. all service are not initialized).
-        cfg = std::make_shared<Service::CFG::Module>();
-        ReadSystemSettings();
+    cfg = Service::CFG::GetModule(system);
+    ReadSystemSettings();
 
+    ui->group_system_settings->setEnabled(enabled);
+    if (enabled) {
         ui->label_disable_info->hide();
     }
 
diff --git a/src/core/frontend/applets/swkbd.cpp b/src/core/frontend/applets/swkbd.cpp
index 12f8b2e25..51f21cda6 100644
--- a/src/core/frontend/applets/swkbd.cpp
+++ b/src/core/frontend/applets/swkbd.cpp
@@ -148,7 +148,6 @@ void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) {
     SoftwareKeyboard::Execute(config_);
 
     auto cfg = Service::CFG::GetModule(Core::System::GetInstance());
-    ASSERT_MSG(cfg, "CFG Module missing!");
     std::string username = Common::UTF16ToUTF8(cfg->GetUsername());
     switch (this->config.button_config) {
     case ButtonConfig::None:
diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp
index 36f401207..db55a6d10 100644
--- a/src/core/hle/service/apt/applet_manager.cpp
+++ b/src/core/hle/service/apt/applet_manager.cpp
@@ -1358,8 +1358,6 @@ void AppletManager::EnsureHomeMenuLoaded() {
     }
 
     auto cfg = Service::CFG::GetModule(system);
-    ASSERT_MSG(cfg, "CFG Module missing!");
-
     auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue());
     auto process = NS::LaunchTitle(FS::MediaType::NAND, menu_title_id);
     if (!process) {
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 0d6505ca2..754230824 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -195,8 +195,6 @@ static u32 DecompressLZ11(const u8* in, u8* out) {
 
 bool Module::LoadSharedFont() {
     auto cfg = Service::CFG::GetModule(system);
-    ASSERT_MSG(cfg, "CFG Module missing!");
-
     u8 font_region_code;
     switch (cfg->GetRegionValue()) {
     case 4: // CHN
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index 6d42c5918..52b982043 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -28,7 +28,9 @@
 #include "core/hle/service/cfg/cfg_nor.h"
 #include "core/hle/service/cfg/cfg_s.h"
 #include "core/hle/service/cfg/cfg_u.h"
+#include "core/loader/loader.h"
 
+SERVICE_CONSTRUCT_IMPL(Service::CFG::Module)
 SERIALIZE_EXPORT_IMPL(Service::CFG::Module)
 
 namespace Service::CFG {
@@ -195,8 +197,10 @@ void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) {
 }
 
 u32 Module::GetRegionValue() {
-    if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT)
+    if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) {
+        UpdatePreferredRegionCode();
         return preferred_region_code;
+    }
 
     return Settings::values.region_value.GetValue();
 }
@@ -599,7 +603,7 @@ void Module::SaveMCUConfig() {
     }
 }
 
-Module::Module() {
+Module::Module(Core::System& system_) : system(system_) {
     LoadConfigNANDSaveFile();
     LoadMCUConfig();
     // Check the config savegame EULA Version and update it to 0x7F7F if necessary
@@ -651,20 +655,23 @@ static std::tuple<u32 /*region*/, SystemLanguage> AdjustLanguageInfoBlock(
     return {default_region, region_languages[default_region][0]};
 }
 
-void Module::SetPreferredRegionCodes(std::span<const u32> region_codes) {
-    const SystemLanguage current_language = GetSystemLanguage();
+void Module::UpdatePreferredRegionCode() {
+    if (!system.IsPoweredOn()) {
+        return;
+    }
+
+    const auto preferred_regions = system.GetAppLoader().GetPreferredRegions();
+    const auto current_language = GetRawSystemLanguage();
     const auto [region, adjusted_language] =
-        AdjustLanguageInfoBlock(region_codes, current_language);
+        AdjustLanguageInfoBlock(preferred_regions, current_language);
 
     preferred_region_code = region;
     LOG_INFO(Service_CFG, "Preferred region code set to {}", preferred_region_code);
 
-    if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) {
-        if (current_language != adjusted_language) {
-            LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}",
-                        current_language, adjusted_language);
-            SetSystemLanguage(adjusted_language);
-        }
+    if (current_language != adjusted_language) {
+        LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}",
+                    current_language, adjusted_language);
+        SetSystemLanguage(adjusted_language);
     }
 }
 
@@ -705,6 +712,13 @@ void Module::SetSystemLanguage(SystemLanguage language) {
 }
 
 SystemLanguage Module::GetSystemLanguage() {
+    if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) {
+        UpdatePreferredRegionCode();
+    }
+    return GetRawSystemLanguage();
+}
+
+SystemLanguage Module::GetRawSystemLanguage() {
     u8 block{};
     GetConfigBlock(LanguageBlockID, sizeof(block), AccessFlag::SystemRead, &block);
     return static_cast<SystemLanguage>(block);
@@ -810,15 +824,21 @@ bool Module::IsSystemSetupNeeded() {
 }
 
 std::shared_ptr<Module> GetModule(Core::System& system) {
-    auto cfg = system.ServiceManager().GetService<Service::CFG::Module::Interface>("cfg:u");
-    if (!cfg)
-        return nullptr;
-    return cfg->GetModule();
+    if (system.IsPoweredOn()) {
+        auto cfg = system.ServiceManager().GetService<Module::Interface>("cfg:u");
+        if (cfg) {
+            return cfg->GetModule();
+        }
+    }
+
+    // If the system is not running or the module is missing,
+    // create an ad-hoc module instance to read data from.
+    return std::make_shared<Module>(system);
 }
 
 void InstallInterfaces(Core::System& system) {
     auto& service_manager = system.ServiceManager();
-    auto cfg = std::make_shared<Module>();
+    auto cfg = std::make_shared<Module>(system);
     std::make_shared<CFG_I>(cfg)->InstallAsService(service_manager);
     std::make_shared<CFG_S>(cfg)->InstallAsService(service_manager);
     std::make_shared<CFG_U>(cfg)->InstallAsService(service_manager);
@@ -826,15 +846,8 @@ void InstallInterfaces(Core::System& system) {
 }
 
 std::string GetConsoleIdHash(Core::System& system) {
-    u64_le console_id{};
+    u64_le console_id = GetModule(system)->GetConsoleUniqueId();
     std::array<u8, sizeof(console_id)> buffer;
-    if (system.IsPoweredOn()) {
-        auto cfg = GetModule(system);
-        ASSERT_MSG(cfg, "CFG Module missing!");
-        console_id = cfg->GetConsoleUniqueId();
-    } else {
-        console_id = std::make_unique<Service::CFG::Module>()->GetConsoleUniqueId();
-    }
     std::memcpy(buffer.data(), &console_id, sizeof(console_id));
 
     std::array<u8, CryptoPP::SHA256::DIGESTSIZE> hash;
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
index bff4021b4..4ac9b3e14 100644
--- a/src/core/hle/service/cfg/cfg.h
+++ b/src/core/hle/service/cfg/cfg.h
@@ -178,7 +178,7 @@ DECLARE_ENUM_FLAG_OPERATORS(AccessFlag);
 
 class Module final {
 public:
-    Module();
+    Module(Core::System& system_);
     ~Module();
 
     class Interface : public ServiceFramework<Interface> {
@@ -445,13 +445,6 @@ private:
 public:
     u32 GetRegionValue();
 
-    /**
-     * Set the region codes preferred by the game so that CFG will adjust to it when the region
-     * setting is auto.
-     * @param region_codes the preferred region codes to set
-     */
-    void SetPreferredRegionCodes(std::span<const u32> region_codes);
-
     // Utilities for frontend to set config data.
     // Note: UpdateConfigNANDSavegame should be called after making changes to config data.
 
@@ -589,6 +582,11 @@ public:
     void SaveMCUConfig();
 
 private:
+    void UpdatePreferredRegionCode();
+    SystemLanguage GetRawSystemLanguage();
+
+    Core::System& system;
+
     static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000;
     std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
     std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
@@ -609,4 +607,5 @@ std::string GetConsoleIdHash(Core::System& system);
 
 } // namespace Service::CFG
 
+SERVICE_CONSTRUCT(Service::CFG::Module)
 BOOST_CLASS_EXPORT_KEY(Service::CFG::Module)
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index bae62a30e..c8b7d46a4 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -100,7 +100,6 @@ void Module::Interface::GetMyScreenName(Kernel::HLERequestContext& ctx) {
     IPC::RequestBuilder rb = rp.MakeBuilder(7, 0);
 
     auto cfg = Service::CFG::GetModule(frd->system);
-    ASSERT_MSG(cfg, "CFG Module missing!");
     auto username = cfg->GetUsername();
     ASSERT_MSG(username.length() <= 10, "Username longer than expected!");
     ScreenName screen_name{};
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index f21c11fa6..deee7c230 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -91,6 +91,14 @@ public:
      */
     virtual FileType GetFileType() = 0;
 
+    /**
+     * Returns the preferred region codes of this file
+     * @return A vector of the preferred region codes
+     */
+    [[nodiscard]] virtual std::span<const u32> GetPreferredRegions() const {
+        return {};
+    }
+
     /**
      * Load the application and return the created Process instance
      * @param process The newly created process.
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 9392c1fb8..04dcf42ce 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -196,8 +196,7 @@ void AppLoader_NCCH::ParseRegionLockoutInfo(u64 program_id) {
         return;
     }
 
-    auto cfg = Service::CFG::GetModule(Core::System::GetInstance());
-    ASSERT_MSG(cfg, "CFG Module missing!");
+    preferred_regions.clear();
 
     std::vector<u8> smdh_buffer;
     if (ReadIcon(smdh_buffer) == ResultStatus::Success && smdh_buffer.size() >= sizeof(SMDH)) {
@@ -205,19 +204,16 @@ void AppLoader_NCCH::ParseRegionLockoutInfo(u64 program_id) {
         std::memcpy(&smdh, smdh_buffer.data(), sizeof(SMDH));
         u32 region_lockout = smdh.region_lockout;
         constexpr u32 REGION_COUNT = 7;
-        std::vector<u32> regions;
         for (u32 region = 0; region < REGION_COUNT; ++region) {
             if (region_lockout & 1) {
-                regions.push_back(region);
+                preferred_regions.push_back(region);
             }
             region_lockout >>= 1;
         }
-        cfg->SetPreferredRegionCodes(regions);
     } else {
         const auto region = Core::GetSystemTitleRegion(program_id);
         if (region.has_value()) {
-            const std::array regions{region.value()};
-            cfg->SetPreferredRegionCodes(regions);
+            preferred_regions.push_back(region.value());
         }
     }
 }
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index b240302de..57ec25c5b 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -30,6 +30,10 @@ public:
         return IdentifyType(file);
     }
 
+    [[nodiscard]] std::span<const u32> GetPreferredRegions() const override {
+        return preferred_regions;
+    }
+
     ResultStatus Load(std::shared_ptr<Kernel::Process>& process) override;
 
     std::pair<std::optional<u32>, ResultStatus> LoadCoreVersion() override;
@@ -87,6 +91,8 @@ private:
     FileSys::NCCHContainer update_ncch;
     FileSys::NCCHContainer* overlay_ncch;
 
+    std::vector<u32> preferred_regions;
+
     std::string filepath;
 };