Skip to content
🚧 DMNO is still in beta! Use with caution!
✨ If you've tried DMNO or looked through the docs, let us know what you think!

Dynamic vs static config

If you do any front-end development, you’re probably used to the concept of replacing references to env vars with actual values at build time (e.g., vite, webpack). This is useful so that:

  • the client doesn’t have to fetch config before using it
  • bundlers can drop unreachable code and dependendencies

In most frameworks and build tools, this concept is tightly coupled with something being “public”, and is triggered via a special prefix (e.g., NEXT_PUBLIC_) but can also be dependent on where and how you access the config, especially now that server-side/hybrid rendering is gaining popularity over the totally static JAMStack sites of the last decade.

Schema to the rescue

In DMNO, rather than relying on name prefixes and tightly coupling the concepts of being secret with being static, we split them and give you explicit control which is easier to reason about:

  • Is the config item sensitive (sensitive: true)
  • Is the config item dynamic (dynamic: true)

Then in your code, simply use DMNO_CONFIG and DMNO_PUBLIC_CONFIG and we take care of the rest, including support for static+secret and dynamic+public config items! We’ll also do our best to help you detect when something unexpected is happening like pre-rendering a dynamic config item, effectively freezing its value on some pages, to help prevent errors and confusion.

Default dynamic behavior

How items are treated by default, with respect to being dynamic, is something that likely depends on the kind of app/service you are building and how it will be deployed. So, we let you control this default behaviour with the settings.dynamicConfig property in your service config.

The following table shows the different modes supported:

non-sensitive = static, sensitive = dynamic
use dynamic: true | false option to override
only_staticeverything static, dynamic not supported
useful for static/SSG sites
only_dynamiceverything dynamic, static not supported
useful for a backend app and not using any bundler
default_staticdefault is static
use dynamic: true to override
default_dynamicdefault is dynamic
use dynamic: false to override

An example service schema using the dynamicConfig service setting and item overrides:

export default defineDmnoService({
settings: {
dynamicConfig: 'default_static',
schema: {
PUBLIC_DYNAMIC: { dynamic: true },
SECRET_STATIC: { sensitive: true },
SECRET_DYNAMIC: { sensitive: true, dynamic: true }

Fetching dynamic config on the client

To support accessing dynamic (i.e., non-sensitive) config in the client, we have to fetch it from the server, and in order to use the same access pattern (i.e., not make every call to get config async like await getConfigItem('SOME_KEY')) we use a blocking http call. This means you should use it sparingly, if at all, and probably not on page load. That said, it’s not that different from making an additional blocking JavaScript request, and we can do some fancy tricks to minimize the impact. We’re working on further tools and options around this in each integration, but it will likely be opt-in or triggered on-demand only as needed.

Obviously a totally pre-rendered static build will not support dynamic config, and some integrations may require a few steps to wire up the endpoint that exposes these config values.

Static secrets

In most cases you won’t need static secrets. The main use case would be to take advantage of tree-shaking, which could be helpful to create a smaller/faster bundle. That said, it’s just another tool in your toolbox - we’re excited to see how you use it.