Configuration items
This page details all configuration fields, types, default values and usage instructions of VextJS.
Configuration loading mechanism
VextJS uses a multi-layer configuration merging strategy, in order of priority from low to high:
The merged configuration is deep-frozen through deepFreeze() and cannot be modified at runtime.
Configuration file list
src/config/bootstrap.ts
When the database, key or configuration center patch needs to be injected before the configuration is frozen, you can add:
Constraints:
- provider must return plain object patch or
null - patch only supports JSON-like structure
- When
requiredis not declared:productiondefaults to fail-fast,development/testdefaults to continue after warning - In Cluster mode, the same provider patch will be reused in the same startup cycle to prevent Master / Worker from seeing different results.
Configuration file example
Complete configuration reference
VextConfig
host accepts "0.0.0.0", "::", an explicit IPv4 address, an explicit IPv6 address, or a hostname. With "::", the ready log prints IPv4 local URLs plus bracketed IPv6 local/network URLs such as http://[::1]:3000; explicit IPv6 hosts are printed with brackets too.
adapter
The underlying HTTP adapter supports three parameter passing methods:
trustProxy
When set to true:
req.ipreads the first IP from theX-Forwarded-Forrequest headerreq.protocolis read from theX-Forwarded-Protorequest header
This option needs to be enabled when deployed behind Nginx/cloud load balancer.
middlewares
Route-level middleware whitelist declaration. Only middleware declared here can be referenced in routes options.middlewares.
Global middleware (such as CORS, body-parser) is automatically registered by the framework and does not need to be declared here. Only routing-level optional middleware is declared here.
The first-party auth() helper is still registered as a route-level middleware file, then routes opt into protection with RouteOptions.auth:
VextCorsConfig
origins: ['*'] and credentials: true cannot be used at the same time. When you need to carry credentials, you must specify a specific domain name.
VextRateLimitConfig
Global rate limit configuration, implemented based on flex-rate-limit.
keyBy option
The routing level can override the global configuration via options.override.rateLimit, or set it to false to disable rate limiting.
VextRequestIdConfig
Request ID tracing configuration for log correlation and distributed link tracing.
requestId vs traceId
requestId is the unique identifier of the request built into vext, and traceId usually refers to the tracing ID generated by the APM link tracking system (such as OpenTelemetry / Jaeger). Both have different usage scenarios:
Mode 1: requestId acts as traceId (simple scenario)
Change the request header name of requestId to x-trace-id to unify it with the link tracking header, which is suitable for systems that do not rely on external APM:
Mode 2: requestId + APM traceId coexist (enterprise-level scenario)
Keep requestId (log association), and transparently transmit APM's traceparent header through config.fetch.propagateHeaders, suitable for connecting to OpenTelemetry / Jaeger and other systems:
- Internal system, simple tracing → Mode 1 (rename header to
x-trace-id) - Access OpenTelemetry / Jaeger / Datadog → Mode 2 (retain requestId, configure propagateHeaders)
- For details, see [Request context → Relationship with distributed tracing](/guide/request-context#Relationship with distributed tracing traceId) :::
Generators can also be replaced dynamically via plugins:
VextFetchConfig
Built-in HTTP client and request proxy configuration.
timeout must be a finite positive number no greater than 2147483647 milliseconds. retryDelay must be a finite non-negative number no greater than 2147483647 milliseconds, and function return values are validated at runtime.
VextFetchProxyTargetConfig
Proxy request header priority: target.headers < forwardHeaders < target.defaultInjectHeaders < options.headers < options.injectHeaders. Authorization does not transmit transparently by default, and both whitelist and allowAuthorizationForward: true must be configured.Agent retry priority: options.retry > target.retry > config.fetch.retry > 0. Only GET / HEAD / OPTIONS / PUT / DELETE will automatically retry when upstream 5xx or network error occurs; POST / PATCH does not retry by default, does not retry when timeout and returns local 504.
VextLoggerConfig
| Structured log configuration, implemented based on Vext’s built-in logger kernel. | Field | Type | Default Value | Description |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------- | -------- | -------------- | ------------------------------ |
| level | 'fatal' \| 'error' \| 'warn' \| 'info' \| 'debug' \| 'trace' \| 'silent' | 'info' | log level |
| lifecycleLevel | 'concise' \| 'verbose' | 'concise' | Framework life cycle log detail level, control system log output such as startup, loader, hot reload, cluster, etc. |
| pretty | boolean | Development environment true | Whether to use the built-in pretty formatter to output readable format |
| prettyIgnore | string | 'pid,hostname,requestId' | Fields to ignore in pretty mode (comma separated). Hiding requestId by default prevents mixin-injected fields from being expanded into multi-line noise, and the production environment JSON output is not affected |
| prettySingleLine | boolean | true | Whether to compress extra fields in the same line of the message as JSON inline in pretty mode. Set to false to use multi-line expansion format. Only affects pretty mode, production environment JSON output is not affected |
| redactKeys | string[] | [] | Desensitize structured log fields by exact key at any level. The top level level is the log protocol field and will not be overwritten |
| redactPaths | string[] | [] | Desensitize structured log fields by dot notation exact path, support array numeric subscript; do not support wildcard, bracket notation, remove or function censor | | redactValue | string | '[Redacted]'' | Desensitized replacement value | | mixin |() => Record<string, unknown> |undefined | Customized log mixin function, the return value will be merged with the framework's built-in fields and injected into each log.requestIdis a framework protected field and cannot be overridden by user mixin; other fields such astrace_id/span_idare given priority by user mixin. Typical use: Inject OpenTelemetrytrace_id/span_id` to associate logs with link tracking. User mixin calls will not be executed when not configured. |
Log level priority (from high to low):
After setting a certain level, only logs of this level and higher will be output. Set to 'silent' to be completely silent.
The default logger also supports runtime app.logger.getLevel() / app.logger.setLevel(level) to adjust subsequent log thresholds; the configuration object itself will still be frozen after startup and should not be dynamically changed by modifying app.config.logger.level.
VextShutdownConfig
Graceful shutdown of configuration.
After receiving the SIGTERM / SIGINT signal, the framework will:
- Stop accepting new requests
- Wait for the in-flight request to complete (no more than
timeoutseconds) - Execute all
onClosehooks in LIFO order - Exit the process
VextServerConfig
Inbound Node.js HTTP server layer configuration. Applicable to built-in Native / Hono / Fastify / Express / Koa adapter, also applicable to development server created by vext dev. Unset fields retain the current Node.js default value.
config.server only controls inbound service requests. The timeout for outbound app.fetch / app.fetch.proxy is controlled by config.fetch.timeout, the proxy target timeout, or options when calling.
VextResponseConfig
Export packaging
When wrap: true is enabled, res.json(data) is automatically wrapped:
Error response format:
When wrap: false is disabled, res.json(data) sends raw data directly.
Hide internal errors
hideInternalErrors only affects the "unknown exception" 500 error path, such as the scenario where throw new Error("...") is directly used in routing, service, and middleware. It does not change the status code and response format of structured errors such as app.throw(...) or VextValidationError.
When hideInternalErrors: true is used, 500 errors are not exposed stack trace:
VextBodyParserConfig
Request body parsing configuration.
After disabled, req.body is always undefined, which is suitable for pure GET service or custom body parsing scenarios.
maxBodySize supported formats:
VextMultipartConfig
Multipart/File upload global configuration.
:::tip Fastify linkage
multipart.maxFileSize only limits the size of a single file; the total request body read limit is controlled by bodyParser.maxBodySize. When using Fastify, if fastifyAdapter({ bodyLimit }) is additionally passed in, the actual read boundary will be the smaller value of the adapter bodyLimit and the overall upper limit of body-parser.
VextAccessLogConfig
Access log output example:
Message fields include HTTP method, path, status code, response time (ms) and client IP; requestId is automatically injected into the JSON record field by logger's AsyncLocalStorage mixin.
VextOpenAPIConfig
OpenAPI documentation generation configuration.
docs.access.cacheKey is not a supported configuration field in this release. Vext rejects it to avoid implying response or access-result caching that the docs access pipeline does not currently provide.
For fixed local or deployed API targets, set servers[].url to the complete base URL including its port, for example http://127.0.0.1:3000. Use servers[].variables only for genuinely variable URL segments such as environment, region, tenant, or API version. docs.tryItOut.defaultServer controls the initial Try it out selection, while docs.tryItOut.customServer lets users temporarily enter another browser-side target without changing project config.
tagGroups is passed through as x-tagGroups only when explicitly configured. The default Vext Docs renderer builds recursive navigation from OpenAPI path segments; tagGroups is mainly for downstream OpenAPI tools that explicitly consume this vendor extension.
The default Vext Docs renderer derives Services / Utils / Models / Components / Plugins / Middlewares from code docs data. Model entries can show static schema fields, enums, options, indexes, methods, hooks, and usage. Plugins and middlewares can show inferred lifecycle/bootstrap, app extensions, middleware type, route usage, and source links. Locales, Config, Styles, and Preload are optional advanced static sources that can be enabled explicitly under docs.code; they are not shown in the default top-level documentation surface. Local loopback pages can also show Open source links for code docs entries without adding a separate configuration field.
guardSecurityMap legacy fallback
Automatically map routing middleware names to OpenAPI Security Scheme for legacy middleware-only routes. New Auth examples should prefer RouteOptions.auth through a local route guard helper so runtime protection and OpenAPI security share the same source:
securitySchemes
Supported security scheme types:
For apiKey schemes with in: "cookie" and for validate.cookie parameters, built-in docs can display the fields but browser Try it out cannot set the forbidden Cookie header directly. Use same-origin browser cookies or an HTTP client for manual cookie values.
VextRequestContextConfig
AsyncLocalStorage request context configuration.
:::warning After disabling, the following functions will be disabled:
- Logger automatically injects
requestId app.throw()automatically parses request-levellocaleapp.fetch()automatically propagatesrequestId:::
VextFrontendConfig
Built-in frontend build and static serving configuration.
By default spaFallback.scopes is empty, so unknown HTML paths are not swallowed into the SPA. For mixed SSR + client-router sub-apps, declare each basePath in scopes[]. spaFallback: true is kept only as a compatibility shorthand and is not recommended for enterprise mixed projects.
VextClusterConfig
Cluster multi-process configuration. For the complete interface definition, see src/types/app.ts VextClusterConfig.
Basic fields
healthCheck — heartbeat detection
reload — Zero-downtime rolling restart
cluster.reload only configures timing for rolling restarts triggered by vext reload / SIGHUP. Omitting cluster.reload does not disable rolling restart; Vext uses the defaults.
It can also be enabled through environment variables (no need to modify the configuration file):
VextCacheConfig
Memory complete configuration:
Redis configuration:
MultiLevel configuration:
cacheHub only accepts response-cache-kit/cache-hub configuration and does not accept custom Store. Route-level response caching is configured via RouteOptions.cache. The public configuration unit is in milliseconds; the Cache-Control: max-age in the response header will output seconds according to the HTTP standard. See the Response Caching Guide for details.
DEFAULT_CONFIG
The full value of the framework’s built-in default configuration:
VextUserConfig
User-configured input type, all fields are optional. The complete VextConfig is generated by loadConfig() merging the default values.
VextSessionConfig
config.session.enabled: true auto-registers Session in production,
development, testing, and soft reload. The explicit session() middleware is
reserved for scoped/manual registration.
VextSessionCookieOptions follows CookieSerializeOptions and adds secure: boolean | "auto". Cookie options include domain, path, expires, maxAge, httpOnly, secure, sameSite, priority, partitioned, and encode.
VextSessionStore requires get(id), set(id, data, ttlSeconds), and delete(id). Optional methods are touch(id, ttlSeconds), clearExpired(), and close(). Vext calls close() during app shutdown for configured stores and active manual Session runtimes.
For cache-backed production sessions, prefer createCacheSessionStore(cacheLike, options?) from vextjs. It accepts a structural VextCacheLike with get, set, and del, converts session TTL seconds to cache milliseconds, stores JSON strings by default, and exposes close() only when options.close is provided. config.cache.cacheHub remains route response cache configuration and does not inject a Session Store.
RouteOptions.session accepts false, true, or { enabled?, rolling?, autoCommit? }. It can disable Session for one route or enable it while the global runtime is disabled.
VextCsrfConfig
config.csrf configures the built-in CSRF middleware. enabled: true auto-registers CSRF globally after body parsing and plugin global middleware. You can also keep it disabled and register csrf() manually for scoped paths.
Routes can opt out with route options { csrf: false }.
VextSecurityHeadersConfig
config.securityHeaders enables Vext's built-in browser security response headers. It is disabled by default. preset: "basic" is the low-impact path for most apps; strict and custom are explicit opt-ins.
basic sends X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and X-Frame-Options: SAMEORIGIN. strict adds HTTPS-only HSTS, a minimal Permissions-Policy, COOP, and CORP, but still leaves CSP and COEP explicit. custom sends only fields you configure. Routes can opt out with { securityHeaders: false }.
loadConfig
Configuration loading function, receives the configuration directory path and performs the complete configuration chain merge.
Usually there is no need to call it manually, bootstrap() will automatically call loadConfig() internally. The merge order is: DEFAULT_CONFIG < default < config profile < local < bootstrap provider patch < CLI override.
Environment variable override
Some configurations support overriding through environment variables:
Type declaration extension
Plug-ins can add custom fields to VextConfig through declare module:
Later use in the configuration file will get full type hints: