Skip to main content
Version: 4.x

Release Notes

See the upgrade guide for migration instructions.

4.3.0 (2026-09-13)​

Highlights, with the full list in the GitHub release:

  • Typed Cloudflare binding providers for the micro API: cloudflareBindings<Env>() tokens for KV, D1, R2 and Queues, resolved per request through req.services, verified inside workerd. See Micro API.
  • Bun as a runtime: expressots dev and expressots prod run the app with Bun when the project uses Bun; override with --runtime or EXPRESSOTS_RUNTIME.
  • AI coding tools: AppFactory returns as a compile-time tombstone that names bootstrap() as the replacement, @expressots/core now ships its llms.txt, and expressots llms prints it for the installed version.
  • Fixes: file log rotation no longer loses lines when two rotations share a millisecond; port recovery runs without a shell; dependency floors raised so npm audit is clean.

What's New in 4.0​

FeatureDescription
InterceptorsAOP system with conditional execution
Testing ModuleZero-config test utilities
Event SystemType-safe events with auto-discovery
Lazy-LoadingOn-demand module loading
ConfigurationType-safe config with validation
Logging11-phase logging system with transports
AuthorizationGuards with permission hierarchy
StudioLocal developer experience platform: request timeline, architecture map, live logs, error inspector, security view

Versioning Scheme​

ExpressoTS follows Semantic Versioning:

  • Major: Breaking changes (roughly yearly)
  • Minor: New features (bi-weekly / monthly)
  • Patch: Bug fixes (as needed)

Releases are bundled. All packages share the same version number:

  • @expressots/core
  • @expressots/adapter-express
  • @expressots/shared
  • @expressots/templates
  • @expressots/cli
  • @expressots/studio
  • @expressots/studio-agent

Support Policy​

Starting with v4.0.0, every major release receives 24 months of bug fixes and security patches from its release date. Releases on the v3.x line and earlier follow the prior 18-month policy. Enterprise customers with support contracts receive extended support.

VersionNode.jsReleaseBug & Security fixed untilStatus
4.0.0>= 20.18.0May 2026May 2028🟢
3.0.0>= 20.18.0December 2024December 2026🟡
2.0.0>= 18.10.0September 2023March 2025🔴

🟢 Active support 🟡 Bug & Security fixes only 🔴 End-of-life

v3.0.0 was originally on the 18-month policy. With v4.0.0 we extended the v3 window by 6 months so users have a smooth transition runway through the rest of 2026.

ExpressoTS 4.0​

Version 4.0.0 introduces significant features and architectural improvements.

Nodejs version​

ExpressoTS v4.0.0 requires Node.js version 20.18.0 or higher.

Core Features​

1. Interceptors System​

AOP system for cross-cutting concerns:

  • whenInterceptor(), unlessInterceptor() for conditional execution
  • Auto-discovery via @provide() + @UseInterceptors()
  • Composition: pipeInterceptors(), combineInterceptors()
  • Built-in: PerformanceInterceptor, LoggingInterceptor, TimeoutInterceptor
import {
UseInterceptors,
PerformanceInterceptor,
whenInterceptor,
} from "@expressots/core";

@controller("/users")
export class UserController {
@Get("/")
@UseInterceptors(
PerformanceInterceptor,
whenInterceptor(
(ctx) => ctx.request.headers["x-cache"] === "true",
CacheInterceptor,
),
)
getUsers() {
return this.userService.findAll();
}
}

2. Testing Module​

Testing utilities for unit, integration, and E2E:

  • createTestApp() for zero-config test setup
  • mockProvider() with dependency auto-suggestion
  • Fluent HTTP testing API
  • Snapshot testing with snapshotRequest()
  • Load testing with percentile metrics
  • Database fixtures with createTestDatabase()
import { createTestApp } from "@expressots/core";

describe("UserController", () => {
let testApp: Awaited<ReturnType<typeof createTestApp>>;

beforeAll(async () => {
testApp = await createTestApp(App);
});

afterAll(async () => {
await testApp.cleanup();
});

test("GET /users returns user list", async () => {
await testApp.request
.get("/users")
.expectStatus(200)
.expectBody<User[]>((users) => users.length > 0)
.expectTime({ lessThan: 100 })
.execute();
});
});

3. Event System​

Type-safe events for decoupled architecture:

  • Event classes with full TypeScript inference
  • Auto-discovery via @OnEvent() decorator
  • Priority-based handler execution
  • Conditional handlers with @When()
  • Event recording and replay
  • Flow visualization
// Type-safe event class
export class UserCreatedEvent {
constructor(
public readonly userId: string,
public readonly email: string,
) {}
}

// Auto-discovered handler
@provide(SendWelcomeEmailHandler)
@OnEvent(UserCreatedEvent, { priority: 1 })
export class SendWelcomeEmailHandler implements IEventHandler<UserCreatedEvent> {
handle(event: UserCreatedEvent) {
// Full TypeScript inference on event payload
this.emailService.sendWelcome(event.email);
}
}

4. Lazy-Loading Modules​

Performance optimization for large applications:

  • On-demand module loading with CreateLazyModule()
  • Route auto-detection from @controller() decorators
  • Preload hints (high, medium, low, never) via .withPreloadHint()
  • Prefetch and timeout configuration via .withLazyConfig()
  • One-liner Express wiring with setupLazyLoadingForExpress()
  • Background warmup strategies (idle, immediate, scheduled)
import { CreateLazyModule } from "@expressots/core";

// Module only loaded when /admin routes are accessed
// (routes auto-detected from @controller("/admin"))
export const AdminModule = CreateLazyModule(
[AdminController],
{ name: "AdminModule" },
).withPreloadHint("never");

5. Enhanced Configuration​

Type-safe configuration with validation:

  • Full TypeScript inference
  • Detailed validation error messages
  • Automatic environment switching
  • SecretValue for secure handling
import { defineConfig, Env } from "@expressots/core";

export default defineConfig({
database: {
url: Env.string("DATABASE_URL", { required: true }),
pool: Env.number("DB_POOL_SIZE", { default: 10 }),
},
features: {
caching: Env.boolean("ENABLE_CACHE", { default: true }),
},
});

Enhanced Logging System​

11-phase production logging:

FeatureDescription
Log LevelsTRACE, DEBUG, INFO, WARN, ERROR, FATAL
Structured LoggingObjects and metadata with formatting
Context ManagementwithContext() and child()
File TransportDaily rotating files, JSON in production
Log QueryingIn-memory buffer with query API
ExportMarkdown export with statistics
RedactionAutomatic sensitive data masking
Flow VisualizationVisual log flow representation
TransportsConsole, File, Custom
import { Logger, LogLevel, FileTransport } from "@expressots/core";

logger.configure({
level: LogLevel.DEBUG,
transports: [FileTransport.daily({ directory: "logs" })],
});

// Query logs
const errors = logger
.query()
.level(LogLevel.ERROR)
.context("UserService")
.search("authentication")
.execute();

// Export to markdown
const report = logger.exportLogsToMarkdown({
query: { level: LogLevel.ERROR },
groupBy: "level",
});

Content Negotiation​

RFC 7231 compliant format negotiation:

  • Formats: JSON, XML, CSV, YAML, Plain Text
  • Quality value support
  • @Consumes() and @Produces() decorators
  • Automatic format selection from Accept headers
import { provide } from "@expressots/core";
import { controller, Get, Produces } from "@expressots/adapter-express";

@provide(UsersController)
@controller("/users")
export class UsersController {
@Get("/")
@Produces("application/json", "application/xml", "text/csv")
getUsers() {
return this.userService.findAll();
}
}

Smart Validation System​

TypeScript-first validation with a pluggable adapter registry:

  • Built-in adapters for class-validator (registered automatically), Zod, and Yup (opt-in via addValidation({ adapters: [...] }))
  • Smart field detection (email, phone, URL, UUID)
  • Helpful error messages with examples
  • Custom adapters via IValidationAdapter
import { provide, ZodValidatorAdapter } from "@expressots/core";
import { controller, Post, validatedBody } from "@expressots/adapter-express";
import { z } from "zod";

// In your App class:
// this.Middleware.addValidation({ adapters: [ZodValidatorAdapter] });

const CreateUser = z.object({
name: z.string(),
email: z.string().email(),
password: z.string().min(8),
});

@provide(UsersController)
@controller("/users")
export class UsersController {
@Post("/")
createUser(@validatedBody(CreateUser) data: z.infer<typeof CreateUser>) {
return this.userService.create(data);
}
}

See the Validation guide for class-validator and Yup variants.

Health Monitoring​

Application health monitoring is built-in at three layers: middleware pipeline, IHealthCheck providers, and an aggregated dashboard. Full deep-dive in the Health & Monitoring guide.

import { AppExpress } from "@expressots/adapter-express";

export class App extends AppExpress {
async configureServices() {
this.Middleware.applyPreset("api");
this.Middleware.addHealthCheck({ path: "/health/middleware", includeMetrics: true });
}
}

Any provider implementing IHealthCheck is auto-discovered and aggregated by ProviderRegistry.checkHealth() so you can expose GET /health from your own controller.

Custom Scopes​

Advanced DI scopes:

  • Tenant, Transaction, Workflow, Session scopes
  • Complete isolation between contexts
  • Manual lifecycle control
import { provideInScope } from "@expressots/core";

@provideInScope(TenantConfigService, "tenant")
export class TenantConfigService {
// Instance shared within tenant, isolated between tenants
}

API Versioning​

  • URL versioning (/v1/users, /v2/users) via the @Version() decorator
  • Controller-level and method-level versions (method overrides controller)
  • Multiple active versions, auto-detected and shown in the startup banner

Route Constraints​

  • Type constraints: UUID, integer, string patterns
  • Custom constraint validators
  • Automatic validation before handler execution

Enhanced Middleware System​

  • Presets: api, production, development
  • Built-in profiler with metrics
  • Pipeline introspection at runtime
  • Conditional execution with when() and unless()
  • Zero-config validation with @validatedBody()

Enhanced Authorization System​

Guard system with advanced access control:

  • Built-in: AuthenticatedGuard, RoleGuard, PermissionGuard, ResourceOwnerGuard
  • ABAC with RequirePolicy()
  • Composition: combineGuards(), sequenceGuards(), whenGuard()
  • Request-scoped caching for performance
  • Permission hierarchy and multi-tenant support
  • Decorators: @RequireAuthentication(), @RequireRoles(), @RequirePermissions()
import { RequireRoles, RequirePermissions } from "@expressots/core";
import { controller, Get } from "@expressots/adapter-express";

@controller("/documents")
export class DocumentController {
@Get("/")
@RequireRoles("user", "admin")
@RequirePermissions("documents:read")
getDocuments() {
return this.documentService.findAll();
}
}

Enhanced Error Handling​

RFC 7807 compliant error handling:

  • Exception filters via @Catch() decorator
  • @UseFilters() at controller and method level
  • AppError helpers: badRequest(), notFound(), validationFailed()
  • Route suggestions for 404 errors
  • Context-aware error hints (disabled in production)

Application Lifecycle Hooks​

AppExpress exposes four lifecycle hooks you can override on your App class. All four are optional and run in the order shown:

import { AppExpress } from "@expressots/adapter-express";

export class App extends AppExpress {
// 1. Synchronous container wiring (custom binds, scopes)
protected globalConfiguration(): void { /* ... */ }

// 2. Async configuration once the container is live
protected async configureServices(): Promise<void> {
this.Middleware.applyPreset("api");
}

// 3. After the HTTP server starts listening
protected async postServerInitialization(): Promise<void> { /* ... */ }

// 4. On SIGINT / SIGTERM, before the process exits
protected async serverShutdown(signal?: NodeJS.Signals): Promise<void> { /* ... */ }
}

Providers can also implement IBootstrap.onBootstrap() and IShutdown.onShutdown(). They're auto-discovered by the lifecycle registry and run alongside the application-level hooks.

CLI Improvements​

The v4 CLI ships with four templates and middleware presets:

TemplateHighlights
applicationCanonical full app: controllers, providers, lifecycle, presets
application-with-eventsSame as above plus the event system pre-wired
microMinimal micro(): single file, fast bootstrap
providerLibrary template for publishing reusable providers (dual ESM/CJS, release-it)

Plus:

  • --preset <api|web|graphql|microservice|minimal> selects the middleware preset for application scaffolds (default: api).
  • --events adds the event system to application scaffolds.
  • --package-manager <npm|pnpm|yarn> for consistent scaffolding.
  • EXPRESSOTS_TEMPLATE_REF, EXPRESSOTS_DEV, EXPRESSOTS_USE_LOCAL_TEMPLATES, EXPRESSOTS_SKIP_INSTALL env switches for CI / local development.
  • expressots create <kind> for in-project code generation.
  • expressots build for production compilation.
  • expressots studio to launch the Studio dashboard.

Studio​

ExpressoTS Studio is the local developer experience platform that ships as part of v4.0.0. Everything runs on your machine; nothing is sent off the box.

  • Status Dashboard: app health, runtime info, DI scope counts, top routes, aggregate security grade.
  • Architecture Map: read-only graph of controllers / use-cases / providers / middleware with DI scope badges and active-path highlighting.
  • Request Timeline + Trace Detail: live recording of every HTTP request with OpenTelemetry spans, headers/body diff, and one-click Replay.
  • Live Logs: in-memory buffer of every framework + app log line, filterable by level, route, and context.
  • Error Inspector: aggregated runtime errors with stack frames and deep-links to source.
  • Security View: npm audit + OSV.dev advisories with transitive root-cause chains, reachability scoring (confirmed / likely / unreachable / unknown), and one-click fixes. OWASP API Top 10 runtime posture findings derived from recorded traffic.
npm install -D @expressots/studio @expressots/studio-agent
npx expressots-studio

The studio-agent dynamically loads only when NODE_ENV=development and the package is installed, so production deployments pay zero runtime cost. See the Studio section for the full tour.

Breaking Changes​

ChangeImpact
Node.js 20.18.0+Update runtime
DI patternsReview injection syntax
Lifecycle hooksUpdate app.ts

See the upgrade guide for migration instructions.


Previous Releases​

For information about previous releases, please see: