Naming Conventions
Consistent naming is one of the highest-leverage investments a team can make. When every engineer follows the same conventions, any file in the codebase becomes immediately readable — even to someone who has never touched that module before.
This document is the single source of truth for naming across all NestJS services and PostgreSQL schemas in this monorepo. When in doubt, refer here first.
NestJS Naming Conventions
Section titled “NestJS Naming Conventions”Modules
Section titled “Modules”- Pattern:
Singular+Module - Rationale: A module is a single, cohesive organizational unit — it encapsulates a domain concept, not a collection.
- Examples:
OrderModule,UserModule,AppointmentModule
Controllers
Section titled “Controllers”- Pattern:
Plural+Controller - Rationale: A controller typically manages multiple endpoints for a resource (
GET /orders,GET /orders/:id,POST /orders). - Examples:
OrdersController,UsersController,AppointmentsController
Services
Section titled “Services”- Pattern:
Plural+Service(or action-based for complex operations) - Rationale: A service provides multiple methods for operating on a resource. For complex workflows, an action-based name is clearer.
- Examples:
OrdersService,UsersService,AppointmentCheckInService
Entities & DTOs
Section titled “Entities & DTOs”- Class name:
Singular,PascalCaseOrder(Entity),CreateOrderDTO(DTO),UpdateOrderDTO(DTO)
- Properties:
snake_case - Rationale: Entity properties map 1-to-1 with PostgreSQL column names (which are conventionally
snake_case). This eliminates the need for@Column({ name: '...' })on every field.
// ✅ Correct entity property namingexport class Order { created_at: Date; total_amount: number; is_fulfilled: boolean; customer_id: string;}- Pattern:
Singular,PascalCase - Rationale: An enum represents a single set of related constants.
- Examples:
OrderStatus,UserRole,PaymentMethod
- Pattern:
kebab-case+.{type}.ts - Rationale: Kebab-case is unambiguous across case-sensitive and case-insensitive filesystems. The type suffix makes the file’s role immediately clear.
| Type | Convention | Example |
|---|---|---|
| Module | Singular | order.module.ts |
| Controller | Plural | orders.controller.ts |
| Service | Plural | orders.service.ts |
| Entity | Singular | order.entity.ts |
| DTO | Singular resource | create-order.dto.ts |
| Events Controller | Singular + -events | order-events.controller.ts |
Folders (Module Directories)
Section titled “Folders (Module Directories)”- Pattern:
Singular+kebab-case - Rationale: The folder represents the domain concept (singular), matching the Module name.
- Examples:
modules/order/,modules/appointment/,modules/notification/
Import Paths
Section titled “Import Paths”Use path aliases instead of relative imports when referencing code across module boundaries:
// ✅ Correct: alias-based importimport { CreateOrderDTO } from '@apps/orders-bc/src/modules/order/dto/create-order.dto';
// ❌ Wrong: fragile relative importimport { CreateOrderDTO } from '../../dto/create-order.dto';Variables & Functions
Section titled “Variables & Functions”- Pattern:
camelCase(standard TypeScript convention) - Examples:
const orderTotal,function calculateDiscount(),const isExpired
Boolean & Status Property Prefixes
Section titled “Boolean & Status Property Prefixes”This is one of the most impactful naming conventions in the codebase. Without prefixes, boolean fields are ambiguous. With them, the field name reads like a question with an obvious yes/no answer.
The Problem with Unprefixed Booleans
Section titled “The Problem with Unprefixed Booleans”| Without Prefix | With Prefix | Why the Prefix Wins |
|---|---|---|
active | is_active | active could be a noun, an adjective, or a verb. is_active unambiguously asks: “Is this currently active?” |
loaded | is_loaded | Past participle or current state? is_loaded is always a state check. |
permission | has_permission | Does the field contain permission data, or indicate that permission exists? |
edit | can_edit | Is this a command or a capability flag? can_edit is always a capability. |
refresh | should_refresh | A stored flag that drives conditional behavior — should_ makes that intent clear. |
The Four Prefix Rules
Section titled “The Four Prefix Rules”| Prefix | Meaning | Examples |
|---|---|---|
is_ | Current state or identity | is_active, is_deleted, is_verified, is_archived |
has_ | Possession or existence of something | has_error, has_permission, has_attachment, has_signature |
can_ | Ability or authorization | can_edit, can_delete, can_approve, can_upload |
should_ | Conditional action or system behavior | should_notify, should_refresh, should_archive, should_validate |
Practical Example
Section titled “Practical Example”// ❌ Ambiguous — what does each field mean?approved: boolean;email_verified: boolean;admin: boolean;public: boolean;
// ✅ Self-documenting — each field answers its own questionis_approved: boolean; // Is this record currently approved?is_email_verified: boolean; // Has the user's email been confirmed?is_admin: boolean; // Does this user have admin privileges?is_public: boolean; // Is this resource accessible without auth?
has_attachments: boolean; // Are there associated file attachments?has_errors: boolean; // Did validation produce errors?
can_edit: boolean; // Is the current user allowed to edit?can_delete: boolean; // Is the current user allowed to delete?
should_notify: boolean; // Should a notification be sent on save?should_archive: boolean; // Should this record be archived on completion?PostgreSQL Naming Conventions
Section titled “PostgreSQL Naming Conventions”Tables
Section titled “Tables”- Pattern:
plural,snake_case - Rationale: A table holds a collection of records, so the plural form is natural.
- Examples:
orders,users,appointment_slots,payment_transactions
Columns
Section titled “Columns”- Pattern:
snake_case - Examples:
first_name,created_at,is_active,total_amount
Primary Keys
Section titled “Primary Keys”- Pattern:
id(column name),pk_<table_name>(constraint name) - Example: Column
idwith constraintpk_orders
Foreign Keys
Section titled “Foreign Keys”- Pattern:
singular_table_name_id(column),fk_<table>_<referenced_table>(constraint) - Example:
customer_idin theorderstable referencingcustomers
Indexes
Section titled “Indexes”- Pattern:
idx_<table_name>_<column_names> - Examples:
idx_orders_customer_id,idx_users_email,idx_appointments_scheduled_at
Unique Constraints
Section titled “Unique Constraints”- Pattern:
uq_<table_name>_<column_names> - Examples:
uq_users_email,uq_orders_reference_number
Check Constraints
Section titled “Check Constraints”- Pattern:
chk_<table_name>_<condition> - Examples:
chk_orders_status,chk_appointments_type
Full Naming Convention Reference
Section titled “Full Naming Convention Reference”| Category | Pattern / Format | Rationale | Examples |
|---|---|---|---|
| Modules | Singular + Module | A module is a single cohesive unit | OrderModule, UserModule |
| Controllers | Plural + Controller | Handles multiple endpoints per resource | OrdersController, UsersController |
| Services | Plural + Service | Provides multiple methods per resource | OrdersService, UsersService |
| Entity Class | Singular, PascalCase | OOP & NestJS convention | Order, User |
| Entity Properties | snake_case | Direct 1-to-1 map to PostgreSQL columns | created_at, is_active |
| DTOs | Singular, PascalCase | Represents a single data transfer shape | CreateOrderDTO, UpdateUserDTO |
| Enums | Singular, PascalCase | Represents a single set of constants | OrderStatus, UserRole |
| Folders | Singular + kebab-case | Matches the domain concept name | order/, appointment/ |
| Filenames | kebab-case + .type.ts | Clear type-to-file mapping | order.entity.ts, orders.service.ts |
| Table Names | plural, snake_case | Plural = collection of records | orders, payment_transactions |
| Column Names | snake_case | PostgreSQL standard convention | first_name, created_at |
| Primary Keys | id / pk_<table> | Consistent PK naming | pk_orders |
| Foreign Keys | <ref_table_singular>_id | Clearly references parent table | customer_id |
| Indexes | idx_<table>_<columns> | Searchable, meaningful index names | idx_orders_customer_id |
| Unique Constraints | uq_<table>_<columns> | Explicit uniqueness enforcement | uq_users_email |
| Check Constraints | chk_<table>_<condition> | DB-level validation naming | chk_orders_status |