Bun Server Best Practices Workflow
Use this skill as an instruction set. Follow the workflow in order unless the user explicitly asks for a different order.
Core Principles
-
Decorator-driven architecture: Use decorators (@Injectable , @Controller , @Module ) as the primary configuration mechanism.
-
Explicit dependency injection: Keep DI contracts clear with Symbol+Interface pattern when needed.
-
Modular organization: Split by feature domain, one module per business boundary.
-
Convention over configuration: Follow established patterns for project structure and module setup.
-
Type safety: Leverage TypeScript decorators and typed contracts throughout.
- Confirm architecture before coding (required)
- Default stack: Bun Runtime + @dangao/bun-server
- TypeScript with decorators enabled.
-
Current stable reference version: @dangao/bun-server v2.0.2 (update docs/examples based on this line unless user pins another version).
-
Verify tsconfig.json has experimentalDecorators: true and emitDecoratorMetadata: true .
1.1 Must-read core references (required)
Before implementing any Bun Server task, make sure to read and apply these core references:
-
quickstart - Project setup, minimal/modular application, common imports
-
dependency-injection - @Injectable, @Inject, scopes, Symbol+Interface pattern
-
module-system - @Module, imports/exports, forRoot pattern, modular architecture
Keep these references in active working context for the entire task.
1.2 Plan module boundaries before coding (required)
Create a brief module map before implementation for any non-trivial feature:
-
Define each module's responsibility in one sentence.
-
Identify which modules need forRoot() configuration (must be called before module definitions).
-
Define provider/export contracts between modules.
-
Follow the recommended project structure:
src/ ├── main.ts # Entry point ├── app.module.ts # Root module ├── common/ # Shared utilities │ ├── middleware/ │ ├── filters/ │ └── guards/ ├── users/ # Feature module │ ├── user.module.ts │ ├── user.controller.ts │ ├── user.service.ts │ └── dto/ └── orders/ # Feature module ├── order.module.ts └── ...
- Apply core framework foundations (required)
These are essential foundations. Apply all of them in every Bun Server task using the core references already loaded in section 1.1 .
Dependency Injection
-
Must-read reference from 1.1 : dependency-injection
-
Mark all services with @Injectable() .
-
Use constructor injection as the primary injection method.
-
Use Symbol+Interface pattern for abstract service contracts.
-
Choose appropriate scopes: Singleton (default), Transient, or Request-scoped.
Controllers and Routing
-
Must-read reference: controller-routing
-
Use @Controller with route prefix for grouping endpoints.
-
Use HTTP method decorators (@GET , @POST , @PUT , @DELETE ) for route definitions.
-
Use parameter decorators (@Body , @Query , @Param , @Header , @Ctx ) for request data binding.
-
Return objects directly for auto JSON serialization; use ResponseBuilder for special responses.
Middleware and Interceptors
-
Must-read reference: middleware
-
Use built-in middleware for common concerns (CORS, logging, rate limiting, static files).
-
Create custom middleware for cross-cutting concerns.
-
Use interceptors for pre/post request processing (logging, transformation, caching).
-
Follow the execution order: Global -> Controller -> Method for both middleware and interceptors.
Validation
-
Must-read reference: validation
-
Define DTOs with validation decorators (@IsString , @IsEmail , @Min , etc.).
-
Use @Validate(DtoClass) on controller methods.
-
Use ValidateNested
- @Type() for nested objects.
- Use PartialType() for update DTOs.
Error Handling
-
Must-read reference: error-handling
-
Use built-in exceptions (NotFoundException , BadRequestException , etc.).
-
Create custom exceptions extending HttpException for domain-specific errors.
-
Register global exception filters for consistent error responses.
-
Async errors in handlers are automatically caught.
- Load official modules only when requirements call for them
Do not add these by default. Load the matching reference only when the requirement exists.
Configuration
- Type-safe config, env vars, config files (.json/.jsonc/.json5), dynamic refresh, Nacos config center -> config
Authentication and Authorization
-
JWT, OAuth2, guards, roles, access control -> security
-
Session management, session stores, user state -> session
Data and Storage
-
Database connections, ORM, entities, repositories, transactions -> database
-
Caching with @Cacheable, cache eviction, Redis cache -> cache
Async Processing
-
Job queues, background tasks, @Cron scheduled tasks -> queue
-
Event-driven architecture, EventModule, @OnEvent (v1.9.0+: auto-scans listeners at app.listen() , no manual initializeListeners needed) -> events
Communication
- WebSocket gateways, real-time features -> websocket
Documentation and Observability
-
API documentation, OpenAPI, Swagger UI -> swagger
-
Health checks, Prometheus metrics, monitoring -> health-metrics
-
Logging, log levels, structured logging -> logger
-
Embedded monitoring Web UI (routes, health, system info) -> dashboard
-
HTTP request recording, debug UI, JSONL export -> debug
Testing and Development Tools
-
Integration tests, module isolation, provider mocking, HTTP test client -> testing
-
Type-safe API client generation from route manifest -> client
AI Application Modules (v2.0+)
-
Unified LLM access, Tool Calling, streaming responses -> ai
-
Includes AiModule , ConversationModule , PromptModule , EmbeddingModule , VectorStoreModule , RagModule , McpModule , AiGuardModule
- Microservice extensions (only when building distributed systems)
Only load when the project explicitly requires microservice architecture:
- Service discovery, config center, load balancing, circuit breaker, distributed tracing -> microservice
- Final self-check before finishing
-
Core behavior works and matches requirements.
-
All must-read references from 1.1 were read and applied.
-
tsconfig.json has experimentalDecorators and emitDecoratorMetadata enabled.
-
DI contracts are explicit: @Injectable() on all services, proper @Inject() where needed.
-
Module boundaries are clear: providers registered, exports declared for cross-module usage.
-
forRoot() calls happen before module definitions for all configurable modules.
-
Controllers use proper parameter decorators and return typed responses.
-
Validation DTOs are defined and applied to controller methods.
-
Error handling follows framework patterns (HttpException, exception filters).
-
Optional modules are used only when requirements demand them.
-
Event listener classes using @OnEvent are registered in a module's providers (required for auto-scan in v1.9.0+).
-
If something is not working, check troubleshooting.