marcoturi/fastify-boilerplate
69.1
Adequate · 21 September 2026
2.5k
lines of production code
TypeScript
with JavaScript
4
measurements over time
What this system is
This system is a Node.js-based API service that manages user lifecycles through a CQRS architecture, supporting user creation, deletion, and paginated filtering. It exposes REST and GraphQL endpoints with strict validation, OpenTelemetry tracing, and automated client type generation. The backend relies on a PostgreSQL database with configurable TLS and connection pooling, ensuring data consistency via domain events and transactional integrity.
Features
Added automated client type generation scripts
New scripts have been added to automate the generation of REST and GraphQL client types. The shell script \scripts/generate-types.sh\ starts the local server, waits for it to become healthy, and then invokes \openapi-typescript\ for REST types and \graphql-codegen\ for GraphQL types, before cleaning up the server process. The accompanying \scripts/codegen.ts\ file provides the configuration for the GraphQL code generator, pointing to the local schema endpoint and outputting TypeScript definitions to \./client/graphql.ts\.
scripts · high confidence
CQRS buses gain OpenTelemetry tracing, ordered event processing, and stricter typing
The CQRS layer now includes OpenTelemetry tracing middleware for commands, queries, and events, wrapping each execution in a span that records action type, bus kind, and correlation ID. The event bus supports ordered per-key processing via a \keyExtractor\ option, ensuring events with the same key are handled sequentially while different keys run concurrently, and isolates async handler failures by logging them instead of rejecting. A new \queryBus\ implementation is introduced alongside the existing command and event buses, and the \EventPublisher\ port allows domain aggregates to publish events via \DomainResult.commit()\. Action types are now strictly branded with phantom symbols to prevent plain-object misuse, and the \actionCreatorFactory\ returns actions with a typed \Result\ parameter. Metadata injection no longer mutates the original action, and execution time logging is lowered to debug level to avoid PII exposure.
src/shared/cqrs · high confidence
OpenTelemetry integration and native ESM migration
The application now includes OpenTelemetry instrumentation for HTTP and Fastify requests, with correlation IDs attached to all log lines and graceful shutdown flushing of telemetry data. The codebase has migrated to native ESM, replacing the previous JSON Schema type provider with TypeBox, and updated the server startup logic to use native process signal handling for graceful shutdown instead of the external graceful-server package.
src · high confidence
Behavioural changes
API error schema expanded and validation constraints tightened
The shared API error response schema now includes a structured array of field-level validation errors (subErrors) instead of a single optional string, providing detailed paths and messages for 400 validation failures. Additionally, the minimum value for the 'limit' query parameter in paginated requests has been increased from 0 to 1, and UUID fields now explicitly specify the 'uuid' format. These changes are supported by a migration from the scoped '@sinclair/typebox' package to the unscoped 'typebox' package.
src/shared/api · high confidence
Add paginated filtered user listing and fix identifier interpolation
Users can now retrieve a paginated, filtered list of users via the new findAllPaginatedFiltered method, supporting filtering by country, street, and postal code. Additionally, the findOneByEmail query now correctly uses identifier interpolation for the table name, ensuring safer and more robust SQL generation.
src/modules/user/database · high confidence
Configurable database TLS and connection pool settings
The application now exposes environment variables to control database security and performance: POSTGRES\_SSL enables TLS for production connections, while POSTGRES\_POOL\_MAX, POSTGRES\_IDLE\_TIMEOUT, and POSTGRES\_CONNECT\_TIMEOUT allow tuning of the connection pool behavior. Additionally, the PORT environment variable now defaults to 3000 if not specified.
src/config · high confidence
Configurable database connections, transaction support, and repository updates
The database layer now supports configurable TLS and connection pool settings via environment variables, with connections created lazily to optimize resource usage. A new \withTransaction\ helper allows executing queries within a database transaction, ensuring atomicity for complex operations. The base SQL repository has been extended with an \update\ method to modify existing records, and pagination now returns an accurate total count from the database rather than the size of the returned page. Additionally, strict typing has been applied throughout the repository and connection logic, removing unsafe \any\ casts and improving error handling.
src/shared/db · high confidence
Dependency injection container updated for ESM and native Node.js paths
The server's dependency injection setup now supports ESM modules by enabling the \esModules\ option in Awilix and switching from \\_\_dirname\ to \import.meta.dirname\ for resolving module paths. The module loading patterns have been expanded to include both \.js\ and \.ts\ extensions, and the \formatName\ utility now uses a more robust regex to split filenames. Additionally, the test suite for this module has been migrated from Vitest to Node's native test runner.
src/server/di · high confidence
Migrate to Node 24, pnpm, and Biome with native TypeScript execution
The project now requires Node.js 24 and uses pnpm instead of Yarn, enabling native TypeScript execution without a build step. ESLint and Prettier have been replaced by Biome for linting and formatting, and Vitest has been removed in favor of Node's built-in test runner. Configuration files for the previous tooling (\.eslintrc.js\, \.prettierrc.json\, \vitest.config.js\, \cucumber.setup.js\) have been deleted, and the \tsconfig.json\ has been updated to support ESM and stricter type checking.
(repo-wide) · high confidence
Migrate to TypeScript-native imports and refine error logging and API documentation
The server plugins now use native TypeScript imports (explicit .ts extensions and import type) and resolve paths via import.meta.dirname to support the production build. Error handling behavior changes so that 4xx domain errors are logged at warn level instead of error, reducing alert noise, while 5xx errors remain logged as errors. Additionally, the Swagger/OpenAPI documentation is enhanced to globally document shared 4xx and 5xx error response schemas for all routes, improving client type generation and API clarity.
src/server/plugins · high confidence
Refactor exception hierarchy and add ProviderErrorException
The exception module has been refactored to use native TypeScript import paths (adding .ts extensions) and the base ExceptionBase class now explicitly exposes cause and metadata properties. A new ProviderErrorException class has been added to handle provider-specific errors, reusing the internal server error status code and message structure. Additionally, the DatabaseErrorException class now explicitly sets its status code to 500 and properly passes the cause to the parent constructor, correcting previous inconsistencies where it might have inherited incorrect defaults.
src/shared/exceptions · high confidence
Server startup order, route loading, and health check improvements
The server now registers security middleware (Helmet and CORS) before GraphQL, ensuring that security headers and CORS policies apply globally to all endpoints, including GraphQL. Route auto-loading has been updated to use ESM-compatible path resolution (\import.meta.dirname\) and a more robust regex filter for \.route.ts\ and \.resolver.ts\ files, fixing issues with route discovery. Additionally, the UnderPressure plugin is now configured with a custom \/health\ endpoint and a silent log level, providing a dedicated health check route without cluttering logs.
src/server · high confidence
Settings creation now logs only user ID instead of full event payload
The event handler for creating default user settings has been updated to prevent logging personally identifiable information (PII). Previously, the entire user creation event (including email and address) was logged; it now logs only the user ID, reducing privacy risks while still tracking the creation action.
src/modules/settings · high confidence
Simplified user deletion logic and explicit 404 error handling
The user deletion command no longer emits a domain event, and the route now explicitly declares a 404 response in the API schema when a user is not found, providing clearer error feedback to clients instead of relying solely on implicit error propagation.
src/modules/user/commands/delete-user · high confidence
Switch from npm/yarn to pnpm and replace lint-staged with Biome
The project's pre-commit and commit-msg hooks have been updated to use pnpm instead of npx/npm for running scripts, and lint-staged has been removed in favor of Biome for pre-commit checks. Users will now see faster hook execution times due to pnpm's efficiency and Biome's integrated linting/formatting, while the commit message validation remains handled by commitlint.
.husky · high confidence
User creation now returns HTTP 201 and publishes domain events via commit()
The Create User API endpoint now returns a 201 Created status code instead of 200, with explicit 409 conflict handling in the route schema. Internally, the command handler uses the domain entity's commit() method to publish events only after the database write succeeds, ensuring consistency. The action creator and handler types have been updated to reflect the result type, and import paths have been standardized to use the \#src alias with .ts extensions.
src/modules/user/commands/create-user · high confidence
User domain now emits domain events on creation
The user creation process in the domain layer now records a 'user/created' domain event alongside the new user entity. This change shifts the responsibility of event publishing to the command handler (which persists the user and then publishes the event), ensuring the domain layer remains decoupled from infrastructure concerns. Additionally, the UserRoles definition was refactored from a TypeScript enum to a const object pattern for better type safety.
src/modules/user/domain · high confidence
User query handling refactored with mapper integration and schema updates
The user listing endpoint now uses a dedicated user mapper to transform database entities into response objects, ensuring consistent data formatting. The underlying query handler has been simplified to rely on a repository method for paginated filtering, removing direct SQL construction. Additionally, the response schema now includes a new 'role' field (admin, moderator, guest), and request validation patterns for country and street fields have been corrected to remove unnecessary regex delimiters.
src/modules/user/queries · high confidence
Users table schema update and performance indexing
The users table now uses UUIDs for the primary key instead of variable-length strings, and constraints have been renamed to more readable identifiers. Additionally, new indexes have been added on the country, postalCode, and street columns to optimize query performance for filtered paginated searches as the dataset grows.
db · high confidence
Test coverage
Migrate user tests from Artillery to k6 and update Cucumber step definitions; Test support infrastructure modernization and isolation.
Dependencies
Updated project dependencies
This release updates the project's dependency manifests, including upgrades to the package manager (yarn to pnpm), the Node.js type definitions (@types/node), and various development tools such as ESLint, TypeScript, and semantic-release.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 65 → 69 (+3.8)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 66 → 70 (+4.4)
- Architecture 100 → 96 (-4.3)
- Maturity 63 → 65 (+2.3)
- Readiness 62 → 69 (+7.2)
- Security 63 → 75 (+11.8)
Resolved (22)
- Coverage not included — suite not readable by the collector
- Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- Medium CVE: [GHSA redacted] (pnpm-lock.yaml)
- No exposed public API
- Off-boarding risk: anonymized user #1
- Test reliability not included
- …and 2 more
New (31)
- Documentation: no installation or build instructions (README.md)
- Documentation: no usage examples (README.md)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- Job token omits the contents scope its checkout needs
- Medium CVE: [GHSA redacted] (pnpm-lock.yaml)
- Medium IaC: WD-COMPOSE-0002 (docker-compose.yml)
- …and 11 more
Changes since last survey
- 104 commits — 70 feature/other, 34 fixes
By area
- (root) — 104 commits
Notable commits
- fix: fix(deps): update dependency @fastify/awilix to v8.2.1 (#1092)
- fix: fix(deps): update dependency @fastify/helmet to v13.1.1 (#1107)
- fix: fix(deps): update dependency @fastify/otel to v0.21.0 (#1134)
- fix: fix(deps): update dependency @graphql-tools/merge to v9.2.3 (#1098)
- fix: fix(deps): update dependency @graphql-tools/merge to v9.2.4 (#1135)
- fix: fix(deps): update dependency fastify to v5.11.2 (#1080)
- fix: fix(deps): update dependency fastify to v5.11.3 (#1090)
- fix: fix(deps): update dependency fastify to v5.12.0 (#1100)
- fix: fix(deps): update dependency fastify to v5.12.1 (#1106)
- fix: fix(deps): update dependency fastify to v5.12.3 (#1131)
- fix: fix(deps): update dependency fastify to v5.12.4 (#1143)
- fix: fix(deps): update dependency fastify to v5.12.5 (#1152)
- fix: fix(deps): update dependency typebox to v1.3.10 (#1079)
- fix: fix(deps): update dependency typebox to v1.3.11 (#1087)
- fix: fix(deps): update dependency typebox to v1.3.12 (#1094)
- fix: fix(deps): update dependency typebox to v1.3.13 (#1097)
- fix: fix(deps): update dependency typebox to v1.3.14 (#1101)
- fix: fix(deps): update dependency typebox to v1.3.15 (#1103)
- fix: fix(deps): update dependency typebox to v1.3.16 (#1108)
- fix: fix(deps): update dependency typebox to v1.3.17 (#1112)
- …and 84 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
marcoturi/fastify-boilerplate was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit fb6b37c5ca0212d878003241560d15f0d7a7f4e4 — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-b84573e22831.