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
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.
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.
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 automatically generates configuration. | Field | Type | Default Value | Description |
| ------------------------------------------------------------ | ---------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------- | -------- | ---- | ------------------------------------------------------------------------------- |
| enabled | boolean | dev is enabled, prod is closed | Whether to enable |
| title | string | undefined | Document title |
| version | string | undefined | Document version number |
| description | string | undefined | Document description |
| docsPath | string | '/docs' | Scalar document path |
| jsonPath | string | '/openapi.json'' | OpenAPI JSON path | | jsonPublicPath |string | Same asjsonPath | Public access path of OpenAPI spec (only affects the URL referencing the spec in Scalar HTML, not routing registration). Used for reverse proxy stripping prefix scenarios, [see the guide for details](/guide/openapi#reverse proxy path prefix scenario) | |contact |object |undefined | Contact information | |license |object |undefined | License information | |servers |array |undefined | Server address list | |tags |array |undefined | Global tag definition | |guardSecurityMap |Record<string, string> |undefined | Guard → Security Scheme mapping | |securitySchemes |object |undefined | Security scheme definition | |scalar|object|{}| Scalar API Reference UI configuration (theme, dark mode, layout, favicon, etc.) | |scalar.theme |string |'default' | Theme:'default'\|'moon'\|'purple'\|'solarized'\|'bluePlanet'\|'saturn'\|'kepler'\|'mars'\|'deepSpace'\|'none' | |scalar.darkMode |boolean |false | Whether to enable dark mode | |scalar.layout |string |'modern' | Layout mode:'modern'(three columns) \|'classic'(two columns) | |scalar.favicon |string |undefined | Document page favicon URL (such as'/favicon.svg') | | scalar.sources |array |undefined | Multiple OpenAPI documentation sources ([see guide for details](/guide/openapi#import external-openapi)). Each item containstitle, urlorcontent, slug | |scalar.cdnUrl |string | jsDelivr CDN | Customize Scalar JS loading address ([see guide for details](/guide/openapi#Use custom address to override local service)). Applicable to intranet/offline/version locked | |scalar.showSidebar |boolean |true | Whether to display the sidebar | |scalar.hideModels |boolean |false | Whether to hide the Models/Schemas panel | |scalar.hiddenClients |string[] |undefined | List of hidden client languages (e.g.['php', 'ruby']) | | scalar.searchHotKey |string |'k' | Search hotkey (Ctrl+K / Cmd+K) | |scalar.proxyUrl |string |undefined | Proxy URL (Try it out request to avoid CORS) | |scalar.customCss |string |undefined | Custom CSS | | ~~tryItOutEnabled~~ | boolean |true | ~~Deprecated~~ Scalar has built-in Try it out, no separate configuration is required | | ~~docExpansion~~ | 'none' | 'list' | 'full'|'list' | ~~Deprecated~~ Please usescalar.layout` instead |
guardSecurityMap
Automatically map routing middleware names to OpenAPI Security Scheme:
securitySchemes
Supported security scheme types:
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
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.
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: