---
title: Retrieve a configuration setting
summary: Resolve a configuration value from developer overrides, the shared cache, or a section reload.
status: draft
owner: SAIF Framework
last_reviewed: 2026-07-30
library: SAIF.Framework.Security.EnvironmentApi
reference_type: package
operation_id: OP-ENV-001
trigger: Caller invokes GetConfigSetting or GetConfigSetting<T>
---

# Retrieve a configuration setting

This is the library's primary configuration-read path, and every consuming application funnels its setting lookups through it. It keeps the shared Environment API cache current, honors a developer-only override file when one applies, falls back to loading a missing section on demand, and throws rather than returning a silent default when a key cannot be resolved anywhere.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-ENV-001 |
| **Trigger** | Caller request to read a configuration value |
| **Inputs** | `configKey` |
| **Outputs** | `string`, converted `T`, or `ApplicationException` |
| **Primary components** | `EnvironmentServiceBase.GetConfigSetting`, `EnvironmentServiceBase.GetConfigSetting<T>`, `EnvironmentServiceBase.GetConfigSettingInfo` |
| **Entry point** | `SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentServiceBase.cs` |

## Steps

1. Validate that `configKey` is not null or empty before any lookup begins.
2. Refresh or initialize the shared settings cache so the lookup runs against the newest known payload ([BR-002](../business-rules.md#br-002-environment-api-base-url-must-be-present), [BR-003](../business-rules.md#br-003-configuration-payload-must-declare-a-refresh-interval)).
   - Check the server refresh timestamp, but only as often as the configured throttle interval allows.
   - Download the full settings payload when the cache is missing or the server reports newer data.

   > **Origin**: Step 2 is expanded in [Refresh configuration cache](refresh-configuration-cache.md) and always runs before this lookup continues.
3. Normalize the requested key to lowercase and determine its logical section. A key without a dot belongs to the global section; a key with a dot uses the text before the first dot as its section ([BR-009](../business-rules.md#br-009-global-section-is-the-sole-non-custom-section)).
4. Check for a developer override before consulting central configuration. If `DeveloperSettingsFile` resolves to an existing JSON file, read and deserialize the override list and return the first entry whose formatted key or global key matches the caller's input ([BR-004](../business-rules.md#br-004-developer-settings-override-requires-developer-machine-status)).
   - If the override file is malformed or unreadable, swallow that exception and fall through to central configuration lookup rather than failing the caller.
5. Check `Configurations.Settings` for the normalized key and return the cached `ConfigSetting` immediately when it is present — this is the common-case, no-network path.
6. If the key belongs to a non-global section and was not already cached, fetch that section from the Environment API and re-check the returned payload for the key ([BR-002](../business-rules.md#br-002-environment-api-base-url-must-be-present), [BR-009](../business-rules.md#br-009-global-section-is-the-sole-non-custom-section)).
   - Download `/v2/settings/{ApplicationId}/{ApplicationHost}/{section}/section`.
   - Merge the returned section entries into the shared cache so later lookups for the same section are served from memory.

   > **Origin**: Step 6 is expanded in [Load a configuration section](load-configuration-section.md) and runs only when a non-global key is missing from the cache.
7. If none of the preceding sources returned the key, throw `ApplicationException` identifying the missing key, track, and section, so a caller never mistakes an absent setting for a valid empty value ([BR-001](../business-rules.md#br-001-configuration-key-must-resolve-or-fail-loudly)).
8. Return the resolved value to the caller.
   - `GetConfigSetting` returns `ConfigValue.Value ?? string.Empty`.
   - `GetConfigSetting<T>` converts the resolved value through `ConfigSetting.GetValue<T>()`.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Caller requests config key]) --> Refresh[Refresh configuration cache]
	Refresh --> SectionKey[Normalize key and section]
	SectionKey --> Override{Developer override match?}
	Override -->|Yes| ReturnOverride([Return override value])
	Override -->|No| Cached{Shared cache has key?}
	Cached -->|Yes| ReturnCache([Return cached value])
	Cached -->|No| NonGlobal{Non-global section?}
	NonGlobal -->|Yes| Load[Load configuration section]
	NonGlobal -->|No| Missing([Throw ApplicationException])
	Load --> Found{Section contains key?}
	Found -->|Yes| ReturnSection([Return section value])
	Found -->|No| Missing
```

## Failure and edge-case behavior

- A null or empty `configKey` fails argument validation before any network call is attempted.
- Malformed developer override JSON is ignored rather than surfaced to the caller, so a broken local override file degrades to central lookup instead of blocking it.
- Keys in the global section never trigger `LoadSection`; only non-global keys can cause an on-demand section fetch.
- A key that is missing from overrides, the cache, and the freshly loaded section throws `ApplicationException` only after every lookup path has been exhausted.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Configuration](../configuration.md)

## Sources
- SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentServiceBase.cs
- SAIF.Framework.Security.EnvironmentApi\Core\Contracts\Core\Configurations\ConfigurationSettings.cs
