AnnouncementsIntroducing Arkoren

    Menu

    Configuration

    Translate application settings into typed construction callbacks while preserving component defaults and ownership.

    What's on this page
    1. Separate required constructor arguments from optional builder settings.
    2. Preserve defaults and reuse typed policies with explicit local overrides.
    3. Read and validate application settings before passing them to components.
    4. Distinguish published settings from shared clients and lifecycle validation.
    On this page

    Your application decides where settings come from; Arkoren components receive the values they need when you construct them. Required dependencies and settings are constructor arguments. Optional settings use a builder callback, a function that edits a temporary construction draft.

    Keep environment and file formats in your application rather than decoding them into package-internal settings. This lets your deployment configuration stay stable as you change components or drivers.

    Component Construction

    With an existing HTTP handler named handler, construct a server using its defaults. Import arkoren.dev/core/http/server:

    listener := server.New(handler)

    The handler is a required dependency. Construction does not bind a socket; Start opens the listener. The generated project registers that startup and cleanup in internal/bootstrap/server.go.

    To select a loopback address, change only that setting during construction:

    listener := server.New(handler, func(listener *server.Builder) {
    	listener.Addr("127.0.0.1:9090")
    })

    These are alternative constructions, not consecutive declarations. The callback changes the address without replacing the server’s other defaults. Its parameter is a *server.Builder, not a server you can reconfigure later. After construction, changing a retained draft does not change the published component.

    Required arguments can also be settings with no safe default, such as a validated signing key or a database connection string. Their validation and provisioning belong to the relevant key or driver guide, not an optional callback.

    Preserving Defaults

    Omit settings you do not need to change. For example, the server’s default header read timeout is 10 seconds; changing its address leaves that timeout in place. Its default address is :8080, which listens on all interfaces, not only loopback. Defaults are not a substitute for application security policy.

    Zero and empty values are package-specific. The server restores its default for an empty address or zero timeout. Its negative write timeout disables the write deadline; that exception is useful for streaming but should not be applied to ordinary endpoints without a reason. Other builders can treat an empty value as an explicit instruction to disable or clear a setting.

    Do not copy every documented default into your callback or assume every collection setting appends. Check the particular method’s contract when replacing lists, clearing values, or disabling protection.

    Shared Policies

    When several listeners need the same header deadline, give that construction policy a typed name. Import time for the duration:

    headers := server.BuilderFunc(func(listener *server.Builder) {
    	listener.ReadHeaderTimeout(5 * time.Second)
    })

    Apply the policy, then add the settings specific to this listener:

    listener := server.New(handler, headers, func(listener *server.Builder) {
    	listener.Addr("127.0.0.1:9090")
    })

    Callbacks run once, synchronously, in argument order on one fresh draft. A later scalar setting replaces an earlier one. server.BuilderFunc is an alias for the ordinary callback type, so it also works in slices passed with policies.... Use the alias belonging to the constructor’s role; a server policy cannot configure a cache or queue consumer.

    To omit optional policies, omit arguments or expand an empty slice. Supplying a nil callback panics; it does not mean “use defaults.” Do not mutate the draft concurrently with construction.

    Environment Settings

    Read values beside the code that constructs their consumer. In the generated internal/bootstrap/server.go, the existing factory callback imports os and constructs its listener with:

    listener := server.New(handler, func(listener *server.Builder) {
    	listener.Addr(os.Getenv("HTTP_ADDR"))
    })

    The factory reads HTTP_ADDR when composition invokes its callback, not when Server(handler) returns the factory. Empty or unset values preserve :8080. Later environment changes do not reconfigure that listener.

    Core packages do not load your application environment or files. The starter’s executable separately imports godotenv/autoload, which reads .env during initialization without overriding process environment values. Its loading errors are ignored, so validate required settings explicitly rather than treating a present .env as proof of valid configuration.

    For example, if you add a required service credential, reject a missing value in your application’s loader before constructing the client. In a function returning an error, with errors and os imported:

    token := os.Getenv("REPORTS_TOKEN")
    if token == "" {
    	return errors.New("REPORTS_TOKEN is required")
    }

    Do not log the token or include it in the error. This validation establishes presence, not authorization or remote reachability. A driver’s documented startup or first operation establishes those later conditions.

    Typed Settings

    Extract a loader when several components share values or parsing becomes substantial. Keep its result application-owned. For example, a server loader could return this type from your own internal/settings package:

    type HTTP struct {
    	Addr            string
    	ShutdownTimeout time.Duration
    }

    Import time in that package. Begin with a zero ShutdownTimeout, preserving the server’s default, and parse an override only when it is present. Inside a loader returning (HTTP, error), use errors, os, and time:

    cfg := HTTP{Addr: os.Getenv("HTTP_ADDR")}
    if value := os.Getenv("HTTP_SHUTDOWN_TIMEOUT"); value != "" {
    	timeout, err := time.ParseDuration(value)
    	if err != nil || timeout <= 0 {
    		return HTTP{}, errors.New("HTTP_SHUTDOWN_TIMEOUT must be a positive duration")
    	}
    	cfg.ShutdownTimeout = timeout
    }

    This application policy permits positive overrides such as 20s; it rejects malformed, zero, or negative input rather than silently changing shutdown behavior. Return cfg, nil after any other application checks. The fragments show the loader’s type and parsing branch, not a complete loader implementation.

    After checking the loader’s error, translate its result into component settings where you construct the server:

    listener := server.New(handler, func(listener *server.Builder) {
    	listener.Addr(cfg.Addr)
    	listener.ShutdownTimeout(cfg.ShutdownTimeout)
    })

    An absent override leaves the server’s 15-second drain default intact. Keep your JSON/YAML schema or environment variable names on HTTP and its loader, not on an Arkoren reporting snapshot. Components that expose Config() do not thereby accept that record as constructor input.

    Validation Boundaries

    Check each constructor’s contract rather than assuming every mistake becomes a returned error at construction. Some constructors return configuration errors; some middleware constructors panic for invalid code-authored policy; reusable definitions can retain domain errors until registration or use. Network and TLS failures can appear during startup. A successful constructor does not establish that a backend is reachable.

    Publication separates owned settings from the temporary draft, not every object reachable from it. Clients, service pointers, functions, captures, and native TLS configuration can remain shared. Finish their setup before concurrent use. Before wrapping a native client with NewFrom, read the driver’s ownership rules: wrapping does not necessarily mean borrowing, and Stop can close that client.

    For startup and cleanup ownership, continue with Lifecycle and Ownership. The server API reference documents the defaults and builder methods used here.

    Open a bulk documentation archive?

    This file contains every guide in its scope, not API declarations. Loading it all into an agent can exhaust its context window and increase processing time and cost. For coding tasks, start with the index and read only the relevant pages.

    Use the full archive for offline indexing, bulk processing, or deliberate large-context use.

    Browse the index instead
    Open archive