- Version: 1.1.2-CE
- Standard: TypeScript + NestJS + Go
- Status: ✅ Enforced
- Overview
- File Naming
- Variable Naming
- Function Naming
- Class Naming
- Database Naming
- API Naming
- Module Naming
- Go Language Conventions
Consistent naming conventions improve code readability, maintainability, and collaboration. TelemetryFlow follows industry-standard conventions for TypeScript and NestJS.
Pattern: {name}.{type}.ts
| File Type | Pattern | Example |
|---|---|---|
| Controller | {module}.controller.ts |
user.controller.ts |
| Service | {module}.service.ts |
user.service.ts |
| Repository | {module}.repository.ts |
user.repository.ts |
| Entity | {name}.entity.ts |
User.entity.ts |
| DTO | {action}-{name}.dto.ts |
create-user.dto.ts |
| Guard | {name}.guard.ts |
auth.guard.ts |
| Interceptor | {name}.interceptor.ts |
logging.interceptor.ts |
| Middleware | {name}.middleware.ts |
cors.middleware.ts |
| Decorator | {name}.decorator.ts |
current-user.decorator.ts |
| Module | {module}.module.ts |
user.module.ts |
| Test | {name}.spec.ts |
user.service.spec.ts |
| E2E Test | {name}.e2e-spec.ts |
user.e2e-spec.ts |
DDD Files:
| File Type | Pattern | Example |
|---|---|---|
| Aggregate | {Name}.ts or {Name}.aggregate.ts |
User.ts |
| Value Object | {Name}Id.ts or {Name}.ts |
UserId.ts |
| Command | {Action}{Name}.command.ts |
CreateUser.command.ts |
| Query | Get{Name}.query.ts |
GetUser.query.ts |
| Handler | {CommandName}.handler.ts |
CreateUser.handler.ts |
| Event | {Name}{Action}Event.ts |
UserCreatedEvent.ts |
| Mapper | {name}-response.mapper.ts |
user-response.mapper.ts |
| File Type | Pattern | Example |
|---|---|---|
| Component | {Name}.vue |
UserCard.vue |
| View | {Name}.vue |
Dashboard.vue |
| Store | {module}-store.ts |
user-store.ts |
| Composable | use{Name}.ts |
useAuth.ts |
| API Client | {module}-api.ts |
user-api.ts |
| Repository | {module}-repository.ts |
user-repository.ts |
| Type | {Name}.ts |
User.ts |
| Test | {name}.spec.ts |
UserCard.spec.ts |
Use camelCase for variables and constants:
// ✅ Good
const userId = 'user_123';
const userName = 'John Doe';
const isActive = true;
const totalCount = 100;
// ❌ Bad
const user_id = 'user_123';
const UserName = 'John Doe';
const is_active = true;Use SCREAMING_SNAKE_CASE for constants:
// ✅ Good
const MAX_RETRY_ATTEMPTS = 3;
const DEFAULT_PAGE_SIZE = 20;
const API_BASE_URL = 'http://localhost:3100';
// ❌ Bad
const maxRetryAttempts = 3;
const default_page_size = 20;Use descriptive names:
// ✅ Good
const userRepository: UserRepository
const createdAt: Date
const isEmailVerified: boolean
// ❌ Bad
const repo: any
const dt: Date
const flag: booleanUse camelCase and verb prefixes:
// ✅ Good - CRUD operations
async function createUser(data: CreateUserDto): Promise<User> {}
async function getUser(id: string): Promise<User> {}
async function updateUser(id: string, data: UpdateUserDto): Promise<User> {}
async function deleteUser(id: string): Promise<void> {}
// ✅ Good - Query operations
async function findUserById(id: string): Promise<User | null> {}
async function findAllUsers(filters: UserFilters): Promise<User[]> {}
async function findActiveUsers(): Promise<User[]> {}
// ✅ Good - Boolean checks
function isUserActive(user: User): boolean {}
function hasPermission(user: User, permission: string): boolean {}
function canAccessResource(user: User, resource: Resource): boolean {}
// ✅ Good - Actions
async function sendEmail(to: string, subject: string): Promise<void> {}
async function validateApiKey(apiKey: string): Promise<boolean> {}
async function transformMetric(metric: RawMetric): Promise<Metric> {}
// ❌ Bad
async function user(id: string): Promise<User> {}
async function getAll(): Promise<User[]> {}
function active(user: User): boolean {}| Prefix | Meaning | Example |
|---|---|---|
| get | Retrieve single item | getUser(), getUserById() |
| find | Search/filter items | findAll(), findByEmail() |
| create | Create new item | createUser(), createOrganization() |
| update | Modify existing item | updateUser(), updateProfile() |
| delete | Remove item | deleteUser(), softDelete() |
| remove | Remove from collection | removePermission() |
| add | Add to collection | addRole(), addMember() |
| is/has/can | Boolean check | isActive(), hasPermission(), canAccess() |
| validate | Validation | validateEmail(), validateApiKey() |
| transform | Data transformation | transformToDto(), mapToEntity() |
| send | Send data/message | sendEmail(), sendNotification() |
| fetch | External data retrieval | fetchFromApi(), fetchMetrics() |
Use PascalCase:
// ✅ Good - Services
export class UserService {}
export class AuthService {}
export class EmailService {}
// ✅ Good - Controllers
export class UserController {}
export class MetricController {}
// ✅ Good - Repositories
export class UserRepository {}
export class MetricRepository {}
// ✅ Good - Entities/Aggregates
export class User {}
export class Organization {}
export class Metric {}
// ✅ Good - Value Objects
export class UserId {}
export class EmailAddress {}
export class TenantId {}
// ✅ Good - DTOs
export class CreateUserDto {}
export class UpdateUserDto {}
export class UserResponseDto {}
// ✅ Good - Commands
export class CreateUserCommand {}
export class UpdateUserCommand {}
// ✅ Good - Queries
export class GetUserQuery {}
export class GetUsersQuery {}
// ✅ Good - Handlers
export class CreateUserHandler {}
export class GetUserHandler {}
// ✅ Good - Events
export class UserCreatedEvent {}
export class UserUpdatedEvent {}
// ❌ Bad
export class userService {}
export class user_repository {}
export class CREATE_USER_DTO {}Use snake_case for tables and columns:
- Pattern: Plural nouns in
snake_case - Examples:
users,organizations,workspaces,tenants,alert_rules,api_keys
- Pattern:
{entity}_id(singular entity name + _id) - Type: UUID (preferred) or BIGINT
- Examples:
- Table
users→ Primary keyuser_id - Table
organizations→ Primary keyorganization_id - Table
alert_rules→ Primary keyalert_rule_id - Table
api_keys→ Primary keyapi_key_id
- Table
❌ AVOID: Generic id without entity name prefix
- Pattern:
{referenced_entity}_id - Examples:
- Reference to users →
user_id - Reference to organizations →
organization_id - Reference to workspaces →
workspace_id - Reference to tenants →
tenant_id
- Reference to users →
- Pattern:
is_{property},has_{property},{property}_enabled - Examples:
is_active,is_system,is_public,is_default,is_favoritehas_permission,has_accessmfa_enabled,email_verified,sso_enabled
❌ AVOID: status_active, active, enabled without prefix
- Pattern:
{action}_ator{state}_at - Type: TIMESTAMP WITH TIME ZONE (timestamptz)
- Standard Columns:
created_at- Record creation timestampupdated_at- Last update timestampdeleted_at- Soft deletion timestamp (NULL if not deleted)
- Action-specific:
last_login_at,last_seen_at,last_heartbeat_atactivated_at,deactivated_atexpires_at,revoked_at,cancelled_atsent_at,delivered_at,read_atscheduled_at,executed_at,completed_at
❌ AVOID: date_activation, create_date, last_login_date
-- ✅ Good - Follows ALL conventions
CREATE TABLE users (
-- Primary Key: {entity}_id pattern
user_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Foreign Keys: {referenced_entity}_id
organization_id UUID NOT NULL REFERENCES organizations(organization_id),
workspace_id UUID REFERENCES workspaces(workspace_id),
tenant_id UUID REFERENCES tenants(tenant_id),
-- Basic fields: snake_case
email VARCHAR(255) NOT NULL UNIQUE,
first_name VARCHAR(100),
last_name VARCHAR(100),
password_hash VARCHAR(255),
-- Boolean fields: is_{property} pattern
is_active BOOLEAN DEFAULT true,
is_system BOOLEAN DEFAULT false,
mfa_enabled BOOLEAN DEFAULT false,
email_verified BOOLEAN DEFAULT false,
-- Timestamp fields: {action}_at pattern
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE,
last_login_at TIMESTAMP WITH TIME ZONE,
-- Audit fields
created_by UUID REFERENCES users(user_id),
updated_by UUID REFERENCES users(user_id),
deleted_by UUID REFERENCES users(user_id)
);
CREATE TABLE organizations (
-- Primary Key
organization_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Foreign Keys
region_id UUID REFERENCES regions(region_id),
-- Fields
organization_code VARCHAR(50) UNIQUE NOT NULL,
organization_name VARCHAR(255) NOT NULL,
-- Boolean fields
is_active BOOLEAN DEFAULT true,
-- Timestamps
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE TABLE alert_rules (
-- Primary Key: Multi-word entities still use singular + _id
alert_rule_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Foreign Keys
workspace_id UUID NOT NULL REFERENCES workspaces(workspace_id),
tenant_id UUID NOT NULL REFERENCES tenants(tenant_id),
created_by UUID REFERENCES users(user_id),
-- Fields
name VARCHAR(255) NOT NULL,
description TEXT,
severity VARCHAR(50),
threshold FLOAT,
-- Boolean fields
is_active BOOLEAN DEFAULT true,
-- Timestamps
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE,
last_evaluated_at TIMESTAMP WITH TIME ZONE,
last_triggered_at TIMESTAMP WITH TIME ZONE
);
-- ❌ Bad - Violates multiple conventions
CREATE TABLE AlertRule (
-- ❌ Generic id without entity prefix
id UUID PRIMARY KEY,
-- ❌ camelCase instead of snake_case
workspaceId UUID,
tenantId UUID,
-- ❌ PascalCase column names
Name VARCHAR(255),
Description TEXT,
-- ❌ Boolean without is_ prefix
active BOOLEAN,
status_active BOOLEAN,
-- ❌ Timestamp without _at suffix
date_creation TIMESTAMP,
last_trigger TIMESTAMP,
create_date TIMESTAMP
);- Pattern:
{entity1}_{entity2}(alphabetical order) - Examples:
role_permissions(notpermission_roles)user_roles(notrole_users)group_users
-- ✅ Good - Junction table
CREATE TABLE role_permissions (
role_id UUID NOT NULL REFERENCES roles(role_id) ON DELETE CASCADE,
permission_id UUID NOT NULL REFERENCES permissions(permission_id) ON DELETE CASCADE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_by UUID REFERENCES users(user_id),
PRIMARY KEY (role_id, permission_id)
);
CREATE TABLE user_roles (
user_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
role_id UUID NOT NULL REFERENCES roles(role_id) ON DELETE CASCADE,
workspace_id UUID REFERENCES workspaces(workspace_id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_by UUID REFERENCES users(user_id),
PRIMARY KEY (user_id, role_id, workspace_id)
);Use snake_case, prefix with telemetry_:
-- ✅ Good
CREATE TABLE telemetry_metrics (
timestamp DateTime64(3),
metric_name LowCardinality(String),
metric_id UUID,
tenant_id UUID,
value Float64,
created_at DateTime DEFAULT now()
) ENGINE = MergeTree()
ORDER BY (tenant_id, metric_name, timestamp);
CREATE TABLE telemetry_logs (
timestamp DateTime64(3),
severity_text LowCardinality(String),
log_body String,
tenant_id UUID
) ENGINE = MergeTree()
ORDER BY (tenant_id, timestamp);
-- ❌ Bad
CREATE TABLE Metrics (
Timestamp DateTime64(3),
MetricName String,
TenantId UUID
);-- ✅ Good - Indexes
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_organization ON users(organization_id);
CREATE INDEX idx_metrics_tenant_time ON telemetry_metrics(tenant_id, timestamp);
-- ✅ Good - Constraints
ALTER TABLE users ADD CONSTRAINT fk_users_organization
FOREIGN KEY (organization_id) REFERENCES organizations(organization_id);
ALTER TABLE users ADD CONSTRAINT uk_users_email UNIQUE (email);
-- ❌ Bad
CREATE INDEX UserEmail ON users(email);
CREATE INDEX idx1 ON users(organization_id);Pattern: {sequence}-{description}.ts
- Sequence: 3-digit number (001, 002, 003)
- Description: kebab-case, descriptive action
- Class Name: PascalCase with timestamp
// ✅ Good - Migration file naming
// File: backend/src/modules/100-core/infrastructure/persistence/postgres/migrations/001-create-users-table.ts
export class CreateUsersTable1732200000000 implements MigrationInterface {
name = 'CreateUsersTable1732200000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE users (
user_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
email VARCHAR(255) NOT NULL UNIQUE,
first_name VARCHAR(100),
last_name VARCHAR(100),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE users`);
}
}
// File: 002-add-mfa-fields-to-users.ts
export class AddMfaFieldsToUsers1732201000000 implements MigrationInterface {
name = 'AddMfaFieldsToUsers1732201000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE users
ADD COLUMN mfa_enabled BOOLEAN DEFAULT false,
ADD COLUMN mfa_secret VARCHAR(255)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE users
DROP COLUMN mfa_enabled,
DROP COLUMN mfa_secret
`);
}
}
// File: 003-create-organizations-table.ts
// File: 004-add-soft-deletion-to-users.ts
// File: 005-create-alert-rules-table.ts
// ❌ Bad - Migration file naming
// CreateUsersTable.ts (missing sequence)
// 1-users.ts (unclear description)
// create_users_table.ts (snake_case instead of kebab-case)
// AddMFA.ts (unclear, missing context)| Pattern | Example |
|---|---|
create-{table} |
001-create-users-table.ts |
add-{field}-to-{table} |
002-add-mfa-fields-to-users.ts |
remove-{field}-from-{table} |
003-remove-deprecated-fields-from-users.ts |
rename-{old}-to-{new} |
004-rename-status-to-is-active.ts |
update-{table}-{description} |
005-update-users-add-indexes.ts |
drop-{table} |
006-drop-deprecated-sessions.ts |
alter-{table}-{description} |
007-alter-users-change-email-length.ts |
Standard: Hyphenated Module-Number Prefix (REQUIRED)
Use the module number followed by a hyphen and sequence number. This provides crystal-clear module identification and prevents numbering conflicts.
Pattern: {module-number}-{sequence}-{function_migration}.ts
Format:
- module-number: The module's numeric identifier (100, 200, 300, etc.)
- sequence: 3-digit sequence number (001, 002, 010, etc.)
- function_migration: Descriptive action in kebab-case
100-core/migrations/
├── 100-001-create-iam-tables.ts
├── 100-002-create-organization-table.ts
├── 100-003-add-soft-deletion.ts
├── 100-999-fix-organization-is-active-column.ts
200-auth/migrations/
├── 200-001-create-auth-sessions-table.ts
├── 200-002-add-mfa-fields-to-users.ts
├── 200-003-create-trusted-devices-table.ts
├── 200-999-rename-id-to-session-id.ts
300-api-keys/migrations/
├── 300-001-create-api-keys-table.ts
├── 300-002-add-rotation-support.ts
├── 300-999-rename-id-to-api-key-id.ts
400-telemetry/migrations/
├── 400-001-create-telemetry-tables.ts
├── 400-999-rename-id-columns.ts
600-alerts/migrations/
├── 600-001-create-alert-rules-table.ts
├── 600-002-add-alert-fatigue-prevention.ts
├── 600-999-rename-id-columns.ts
900-dashboard/migrations/
├── 900-001-create-dashboard-templates.ts
├── 900-002-create-dashboards.ts
├── 900-003-create-widgets.ts
1000-subscription/migrations/
├── 1000-001-create-subscription-tables.ts
├── 1000-999-rename-id-columns.ts
1100-agents/migrations/
├── 1100-001-create-agents-table.ts
├── 1100-002-add-soft-deletion-to-agents.ts
├── 1100-999-rename-status-and-date-columns.ts
1500-retention/migrations/
├── 1500-001-create-retention-policies-table.ts
├── 1500-999-rename-id-to-retention-policy-id.ts
Benefits:
- ✅ Crystal-clear module identification - Module number is explicit
- ✅ No numbering conflicts - Each module has isolated sequence
- ✅ Perfect sorting - Files group by module naturally
- ✅ Easy to search - Can grep for "200-" to find all auth migrations
- ✅ Scalable - Supports up to 999 migrations per module
Examples:
// Module 200 (auth), sequence 010
// File: 200-999-rename-id-to-session-id.ts
export class RenameIdToSessionId1734134400000 implements MigrationInterface {
name = 'RenameIdToSessionId1734134400000';
public async up(queryRunner: QueryRunner): Promise<void> {
// Migration code
}
}
// Module 600 (alerts), sequence 010
// File: 600-999-rename-id-columns.ts
export class RenameIdColumns1734134700000 implements MigrationInterface {
name = 'RenameIdColumns1734134700000';
public async up(queryRunner: QueryRunner): Promise<void> {
// Migration code
}
}❌ AVOID:
- Generic numbering:
001-create-table.ts(no module context) - Concatenated:
100001-create-table.ts(hard to read) - Wrong separator:
100_001_create_table.ts(use hyphens)
Pattern: {unixtimestamp}-seed-{module_name}-{submodule_or_function}.ts
- Unix Timestamp: 13-digit millisecond timestamp for chronological ordering
- Module Name: Short module identifier (core, auth, api-keys, telemetry, etc.)
- Submodule/Function: Specific domain area or functional component
Why Unix Timestamps?
- ✅ Guaranteed unique ordering
- ✅ Chronological execution sequence
- ✅ No conflicts between developers
- ✅ Self-documenting creation time
// ✅ Good - Seed file naming with unix timestamps
// Module: 100-core
// File: 1704240000101-seed-core-iam-permissions.ts
export class SeedCoreIamPermissions1704240000101 implements Seeder {
public async run(dataSource: DataSource): Promise<void> {
const permissionRepository = dataSource.getRepository(Permission);
const permissions = [
{ permission_id: uuid(), name: 'users:read', description: 'Read users' },
{ permission_id: uuid(), name: 'users:write', description: 'Create/update users' },
{ permission_id: uuid(), name: 'users:delete', description: 'Delete users' },
];
await permissionRepository.save(permissions);
}
}
// File: 1704240000102-seed-core-iam-roles.ts
export class SeedCoreIamRoles1704240000102 implements Seeder {
// Seed default roles: super_admin, admin, developer, viewer, demo
}
// File: 1704240000103-seed-core-tenancy-regions.ts
export class SeedCoreTenancyRegions1704240000103 implements Seeder {
// Seed regions: us-east, eu-west, ap-south
}
// Module: 200-auth
// File: 1704240100201-seed-auth-default-users.ts
export class SeedAuthDefaultUsers1704240100201 implements Seeder {
// Seed default users for testing
}
// File: 1704240100202-seed-auth-test-sessions.ts
export class SeedAuthTestSessions1704240100202 implements Seeder {
// Seed auth sessions for development
}
// Module: 600-alerts
// File: 1704240600601-seed-alerts-default-rules.ts
export class SeedAlertsDefaultRules1704240600601 implements Seeder {
// Seed 33 production-ready alert rules
}
// Module: 900-dashboard
// File: 1704240900901-seed-dashboard-system-monitoring-template.ts
export class SeedDashboardSystemMonitoringTemplate1704240900901 implements Seeder {
// Seed system monitoring dashboard template
}
// File: 1704240900902-seed-dashboard-apm-template.ts
export class SeedDashboardApmTemplate1704240900902 implements Seeder {
// Seed APM dashboard template
}
// ❌ Bad - Seed file naming
// permissions.seed.ts (missing timestamp and module context)
// seed-data.ts (too generic, no timestamp)
// default-roles.ts (missing seed prefix and timestamp)
// 001-permissions.ts (sequential number instead of timestamp)
// seed-core-permissions.ts (missing timestamp)| Module | Pattern Example | Purpose |
|---|---|---|
| 100-core | 1704240000101-seed-core-iam-permissions.ts |
IAM permissions |
1704240000102-seed-core-iam-roles.ts |
IAM roles | |
1704240000103-seed-core-tenancy-regions.ts |
Multi-tenancy regions | |
| 200-auth | 1704240100201-seed-auth-default-users.ts |
Default test users |
1704240100202-seed-auth-mfa-secrets.ts |
MFA test data | |
| 300-api-keys | 1704240300301-seed-api-keys-test-keys.ts |
Test API keys |
| 600-alerts | 1704240600601-seed-alerts-default-rules.ts |
Default alert rules |
| 900-dashboard | 1704240900901-seed-dashboard-system-monitoring.ts |
Dashboard templates |
# Generate current unix timestamp (milliseconds)
date +%s%3N
# Generate timestamp for specific date
date -d "2025-01-15 10:00:00" +%s%3N
# In Node.js
Date.now() // Returns millisecond timestampPattern: Seed{ModuleName}{Purpose}{Timestamp}
// File: 1704240000101-seed-core-iam-permissions.ts
export class SeedCoreIamPermissions1704240000101 implements Seeder {
// Class name matches file purpose
}
// File: 1704240900901-seed-dashboard-system-monitoring-template.ts
export class SeedDashboardSystemMonitoringTemplate1704240900901 implements Seeder {
// Class name is PascalCase version of file purpose
}Use kebab-case, plural nouns:
# ✅ Good - Resource collections
GET /api/v1/users
POST /api/v1/users
GET /api/v1/users/:id
PATCH /api/v1/users/:id
DELETE /api/v1/users/:id
# ✅ Good - Nested resources
GET /api/v1/organizations/:orgId/workspaces
GET /api/v1/workspaces/:workspaceId/tenants
# ✅ Good - Actions (non-CRUD)
POST /api/v1/users/:id/activate
POST /api/v1/users/:id/deactivate
POST /api/v1/api-keys/:id/revoke
# ✅ Good - Queries
GET /api/v1/metrics?metric_name=cpu_usage&start_time=1699564800
GET /api/v1/logs?severity=ERROR&limit=100
# ❌ Bad
GET /api/v1/getUsers
GET /api/v1/user
POST /api/v1/createUser
GET /api/v1/UsersUse snake_case:
# ✅ Good
GET /api/v1/metrics?metric_name=cpu_usage&start_time=1699564800&end_time=1699651200
# ❌ Bad
GET /api/v1/metrics?metricName=cpu_usage&startTime=1699564800&endTime=1699651200Use snake_case for JSON keys:
// ✅ Good
{
"user_id": "user_123",
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"is_active": true,
"created_at": "2025-12-12T10:00:00Z"
}
// ❌ Bad
{
"userId": "user_123",
"Email": "john@example.com",
"firstName": "John",
"isActive": true
}Use numbers + kebab-case:
modules/
├── 100-core/ # IAM, Multi-tenancy, RBAC
├── 200-auth/ # Authentication
├── 300-api-keys/ # API Keys
├── 400-telemetry/ # OTLP Ingestion
├── 500-monitoring/ # Uptime Monitors
├── 600-alerts/ # Alert Rules
├── 700-sso/ # Single Sign-On
├── 800-audit/ # Audit Logging
├── 900-dashboard/ # Dashboard Templates
├── 1000-subscription/ # Subscription Management
├── 1100-agents/ # Agent Management
├── 1200-status-page/ # Status Pages
├── 1300-export/ # Data Export
├── 1400-query-builder/ # Visual Query Builder
└── 1500-retention-policy/ # Data Retention
Use kebab-case:
modules/
├── auth/
├── telemetry/
├── iam/
├── monitoring/
└── api-keys/
Based on Effective Go, Go Code Review Comments, and Google Go Style Guide.
Use snake_case for file names:
| File Type | Pattern | Example |
|---|---|---|
| Main Package | main.go |
main.go |
| Package File | {feature}.go |
order.go, user.go |
| Test File | {feature}_test.go |
order_test.go |
| Platform-Specific | {feature}_{os}.go |
file_linux.go, file_windows.go |
| Architecture-Specific | {feature}_{arch}.go |
asm_amd64.go |
| Platform + Arch | {feature}_{os}_{arch}.go |
syscall_linux_amd64.go |
DDD/Clean Architecture Files:
| File Type | Pattern | Example |
|---|---|---|
| Entity | {entity}.go |
order.go, user.go |
| Repository Interface | {entity}_repository.go |
order_repository.go |
| Repository Impl | {entity}_repository_{driver}.go |
order_repository_postgres.go |
| Service | {entity}_service.go |
order_service.go |
| Handler | {entity}_handler.go |
order_handler.go |
| DTO | {entity}_dto.go |
order_dto.go |
| Mapper | {entity}_mapper.go |
order_mapper.go |
Use short, lowercase, single-word names:
// ✅ Good - Short, lowercase, no underscores
package order
package user
package config
package http
package grpc
package postgres
package telemetry
// ✅ Good - Domain packages
package domain // Domain entities and value objects
package repository // Repository interfaces
package service // Business logic
package handler // HTTP/gRPC handlers
package dto // Data Transfer Objects
package mapper // Entity-DTO mappers
// ❌ Bad - Multi-word, underscores, camelCase
package orderService
package order_service
package OrderService
package userManagement
package util // Too generic - be specific
package common // Too generic - be specific
package helpers // Too generic - be specific
package misc // Too vaguePackage Path Conventions:
github.com/telemetryflow/order-service/
├── cmd/
│ └── order-service/
│ └── main.go # package main
├── internal/
│ ├── domain/
│ │ ├── order/
│ │ │ ├── order.go # package order
│ │ │ ├── order_status.go
│ │ │ └── order_item.go
│ │ └── customer/
│ │ └── customer.go # package customer
│ ├── application/
│ │ └── order/
│ │ ├── service.go # package order
│ │ ├── command.go
│ │ └── query.go
│ ├── infrastructure/
│ │ ├── persistence/
│ │ │ └── postgres/
│ │ │ └── order_repository.go # package postgres
│ │ └── http/
│ │ └── order_handler.go # package http
│ └── config/
│ └── config.go # package config
├── pkg/
│ ├── safefile/
│ │ └── safefile.go # package safefile
│ └── validator/
│ └── validator.go # package validator
└── tests/
├── unit/
│ └── order_test.go
├── integration/
│ └── order_integration_test.go
└── e2e/
└── order_e2e_test.go
Use camelCase for variables, MixedCaps for exported:
// ✅ Good - Local variables (camelCase)
var orderID string
var userName string
var isActive bool
var totalCount int
var httpClient *http.Client
var dbConnection *sql.DB
// ✅ Good - Exported variables (MixedCaps/PascalCase)
var DefaultTimeout = 30 * time.Second
var MaxRetryAttempts = 3
// ✅ Good - Short names for short scopes
for i := 0; i < len(items); i++ { }
for _, v := range values { }
if err != nil { return err }
// ✅ Good - Acronyms: ALL CAPS or all lowercase
var userID string // Not userId
var httpURL string // Not httpUrl
var xmlParser Parser // Not XmlParser
var apiKey string // Not APIkey (consistent casing)
var urlPath string // Not URLPath in local scope
// ❌ Bad - snake_case, wrong acronym casing
var user_id string
var user_name string
var httpUrl string // Should be httpURL
var UserId string // Should be UserID (exported)Common Acronym Conventions:
| Acronym | Exported | Unexported |
|---|---|---|
| ID | UserID, OrderID |
userID, orderID |
| URL | ImageURL, APIURL |
imageURL, apiURL |
| HTTP | HTTPClient, HTTPServer |
httpClient, httpServer |
| API | APIKey, APIVersion |
apiKey, apiVersion |
| JSON | JSONEncoder |
jsonEncoder |
| XML | XMLParser |
xmlParser |
| SQL | SQLQuery |
sqlQuery |
| TCP/UDP | TCPConn, UDPAddr |
tcpConn, udpAddr |
| UUID | UserUUID |
userUUID |
| GRPC | GRPCServer |
grpcServer |
| OTLP | OTLPExporter |
otlpExporter |
Use MixedCaps (NOT SCREAMING_SNAKE_CASE):
// ✅ Good - Go style constants
const (
MaxRetryAttempts = 3
DefaultPageSize = 20
DefaultTimeout = 30 * time.Second
// Grouped related constants
StatusPending = "pending"
StatusActive = "active"
StatusCompleted = "completed"
StatusCancelled = "cancelled"
)
// ✅ Good - Unexported constants
const (
maxBufferSize = 1024
defaultBatchSize = 100
retryDelay = 5 * time.Second
)
// ✅ Good - iota for enumerations
type OrderStatus int
const (
OrderStatusPending OrderStatus = iota
OrderStatusConfirmed
OrderStatusShipped
OrderStatusDelivered
OrderStatusCancelled
)
// String method for OrderStatus
func (s OrderStatus) String() string {
return [...]string{
"pending",
"confirmed",
"shipped",
"delivered",
"cancelled",
}[s]
}
// ❌ Bad - SCREAMING_SNAKE_CASE (not Go style)
const MAX_RETRY_ATTEMPTS = 3
const DEFAULT_PAGE_SIZE = 20
const STATUS_PENDING = "pending"Use MixedCaps, verb prefixes, descriptive names:
// ✅ Good - Exported functions (PascalCase)
func CreateOrder(ctx context.Context, req CreateOrderRequest) (*Order, error) {}
func GetOrderByID(ctx context.Context, id string) (*Order, error) {}
func ListOrders(ctx context.Context, filter OrderFilter) ([]*Order, error) {}
func UpdateOrder(ctx context.Context, id string, req UpdateOrderRequest) (*Order, error) {}
func DeleteOrder(ctx context.Context, id string) error {}
// ✅ Good - Unexported functions (camelCase)
func validateOrder(order *Order) error {}
func calculateTotal(items []OrderItem) decimal.Decimal {}
func formatOrderID(id string) string {}
// ✅ Good - Boolean functions (use Is, Has, Can, Should)
func IsValidEmail(email string) bool {}
func HasPermission(user *User, permission string) bool {}
func CanAccessResource(user *User, resource *Resource) bool {}
func ShouldRetry(err error) bool {}
// ✅ Good - Constructors (New prefix)
func NewOrderService(repo OrderRepository) *OrderService {}
func NewHTTPClient(opts ...ClientOption) *Client {}
func NewConfig(path string) (*Config, error) {}
// ✅ Good - Factory functions for interfaces
func NewRepository(db *sql.DB) Repository {} // Returns interface
// ✅ Good - Methods on types
func (o *Order) Total() decimal.Decimal {}
func (o *Order) AddItem(item OrderItem) {}
func (o *Order) Cancel() error {}
func (o *Order) IsCompleted() bool {}
// ❌ Bad - Poor naming
func order(id string) (*Order, error) {} // Not descriptive
func GetAll() ([]*Order, error) {} // Missing context
func DoOrder(req Request) error {} // Vague verb
func ProcessIt(data interface{}) error {} // "It" is unclear
func HandleStuff(ctx context.Context) error {} // "Stuff" is vagueFunction Verb Prefixes:
| Prefix | Purpose | Example |
|---|---|---|
| Get | Retrieve single item | GetOrderByID(), GetUser() |
| List | Retrieve collection | ListOrders(), ListUsers() |
| Find | Search with criteria | FindByEmail(), FindActive() |
| Create | Create new item | CreateOrder(), CreateUser() |
| Update | Modify existing | UpdateOrder(), UpdateProfile() |
| Delete | Remove item | DeleteOrder(), DeleteUser() |
| New | Constructor | NewService(), NewClient() |
| Parse | Parse input | ParseConfig(), ParseJSON() |
| Format | Format output | FormatDate(), FormatMoney() |
| Validate | Validation | ValidateEmail(), ValidateOrder() |
| Is/Has/Can | Boolean check | IsValid(), HasAccess(), CanRetry() |
| Must | Panics on error | MustParse(), MustCompile() |
| With | Builder pattern | WithTimeout(), WithRetry() |
Single-method interfaces: use verb + "er" suffix:
// ✅ Good - Single method interfaces (verb + er)
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
type Stringer interface {
String() string
}
type Validator interface {
Validate() error
}
// ✅ Good - Combined interfaces
type ReadWriter interface {
Reader
Writer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
// ✅ Good - Domain interfaces (descriptive names)
type OrderRepository interface {
Create(ctx context.Context, order *Order) error
GetByID(ctx context.Context, id string) (*Order, error)
List(ctx context.Context, filter OrderFilter) ([]*Order, error)
Update(ctx context.Context, order *Order) error
Delete(ctx context.Context, id string) error
}
type OrderService interface {
CreateOrder(ctx context.Context, req CreateOrderRequest) (*Order, error)
GetOrder(ctx context.Context, id string) (*Order, error)
CancelOrder(ctx context.Context, id string) error
}
type MetricExporter interface {
Export(ctx context.Context, metrics []Metric) error
Shutdown(ctx context.Context) error
}
// ✅ Good - Handler interfaces
type Handler interface {
ServeHTTP(w http.ResponseWriter, r *http.Request)
}
type MessageHandler interface {
Handle(ctx context.Context, msg Message) error
}
// ❌ Bad - "I" prefix (not Go style)
type IOrderRepository interface {} // Don't use I prefix
type IUserService interface {} // Don't use I prefix
// ❌ Bad - "Interface" suffix
type OrderRepositoryInterface interface {} // Redundant
type UserServiceInterface interface {} // RedundantUse MixedCaps, descriptive names:
// ✅ Good - Domain entities
type Order struct {
ID string `json:"id"`
CustomerID string `json:"customer_id"`
Items []OrderItem `json:"items"`
Status OrderStatus `json:"status"`
TotalAmount decimal.Decimal `json:"total_amount"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type OrderItem struct {
ProductID string `json:"product_id"`
ProductName string `json:"product_name"`
Quantity int `json:"quantity"`
UnitPrice decimal.Decimal `json:"unit_price"`
}
// ✅ Good - Value Objects
type Money struct {
Amount decimal.Decimal
Currency string
}
type Address struct {
Street string
City string
State string
PostalCode string
Country string
}
// ✅ Good - DTOs (Request/Response)
type CreateOrderRequest struct {
CustomerID string `json:"customer_id" validate:"required,uuid"`
Items []OrderItemRequest `json:"items" validate:"required,min=1"`
}
type OrderResponse struct {
ID string `json:"id"`
CustomerID string `json:"customer_id"`
Items []OrderItemResponse `json:"items"`
TotalAmount string `json:"total_amount"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
}
// ✅ Good - Configuration
type Config struct {
Server ServerConfig `yaml:"server"`
Database DatabaseConfig `yaml:"database"`
Redis RedisConfig `yaml:"redis"`
OTEL OTELConfig `yaml:"otel"`
}
type ServerConfig struct {
Host string `yaml:"host" env:"SERVER_HOST" default:"0.0.0.0"`
Port int `yaml:"port" env:"SERVER_PORT" default:"8080"`
ReadTimeout time.Duration `yaml:"read_timeout" default:"30s"`
WriteTimeout time.Duration `yaml:"write_timeout" default:"30s"`
}
// ✅ Good - Options pattern
type ClientOption func(*Client)
type Client struct {
baseURL string
httpClient *http.Client
timeout time.Duration
retries int
}
func WithTimeout(d time.Duration) ClientOption {
return func(c *Client) {
c.timeout = d
}
}
func WithRetries(n int) ClientOption {
return func(c *Client) {
c.retries = n
}
}
// ❌ Bad - Hungarian notation, poor naming
type TOrder struct {} // T prefix
type OrderStruct struct {} // Struct suffix
type order_data struct {} // snake_caseUse Err prefix for sentinel errors, descriptive messages:
// ✅ Good - Sentinel errors (package-level)
var (
ErrNotFound = errors.New("not found")
ErrAlreadyExists = errors.New("already exists")
ErrInvalidInput = errors.New("invalid input")
ErrUnauthorized = errors.New("unauthorized")
ErrForbidden = errors.New("forbidden")
ErrInternal = errors.New("internal error")
)
// ✅ Good - Domain-specific errors
var (
ErrOrderNotFound = errors.New("order not found")
ErrOrderCancelled = errors.New("order already cancelled")
ErrInsufficientStock = errors.New("insufficient stock")
ErrPaymentFailed = errors.New("payment failed")
)
// ✅ Good - Custom error types
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error on field %s: %s", e.Field, e.Message)
}
type NotFoundError struct {
Entity string
ID string
}
func (e *NotFoundError) Error() string {
return fmt.Sprintf("%s with id %s not found", e.Entity, e.ID)
}
// ✅ Good - Error wrapping
func GetOrder(ctx context.Context, id string) (*Order, error) {
order, err := repo.GetByID(ctx, id)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("order %s: %w", id, ErrNotFound)
}
return nil, fmt.Errorf("get order %s: %w", id, err)
}
return order, nil
}
// ❌ Bad - Poor error naming
var NotFoundErr = errors.New("not found") // Should be ErrNotFound
var ORDER_ERROR = errors.New("error") // SCREAMING_SNAKE_CASE
var error1 = errors.New("error") // Non-descriptiveUse Test prefix, descriptive names with underscores:
// ✅ Good - Test function naming
func TestOrderService_CreateOrder(t *testing.T) {}
func TestOrderService_CreateOrder_Success(t *testing.T) {}
func TestOrderService_CreateOrder_InvalidInput(t *testing.T) {}
func TestOrderService_CreateOrder_DuplicateOrder(t *testing.T) {}
// ✅ Good - Table-driven tests
func TestCalculateTotal(t *testing.T) {
tests := []struct {
name string
items []OrderItem
expected decimal.Decimal
wantErr bool
}{
{
name: "single item",
items: []OrderItem{{Quantity: 1, UnitPrice: decimal.NewFromInt(100)}},
expected: decimal.NewFromInt(100),
wantErr: false,
},
{
name: "multiple items",
items: []OrderItem{
{Quantity: 2, UnitPrice: decimal.NewFromInt(50)},
{Quantity: 1, UnitPrice: decimal.NewFromInt(75)},
},
expected: decimal.NewFromInt(175),
wantErr: false,
},
{
name: "empty items",
items: []OrderItem{},
expected: decimal.Zero,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := calculateTotal(tt.items)
if (err != nil) != tt.wantErr {
t.Errorf("calculateTotal() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !got.Equal(tt.expected) {
t.Errorf("calculateTotal() = %v, want %v", got, tt.expected)
}
})
}
}
// ✅ Good - Benchmark naming
func BenchmarkOrderService_CreateOrder(b *testing.B) {}
func BenchmarkCalculateTotal(b *testing.B) {}
// ✅ Good - Example naming (for documentation)
func ExampleOrderService_CreateOrder() {}
func ExampleNewOrderService() {}
// ❌ Bad - Poor test naming
func Test1(t *testing.T) {} // Non-descriptive
func TestCreateOrderWorks(t *testing.T) {} // Not structured
func Testcreateorder(t *testing.T) {} // Wrong casingStandard Go project layout:
project-name/
├── cmd/ # Main applications
│ ├── api/
│ │ └── main.go # API server entry point
│ └── worker/
│ └── main.go # Background worker entry point
├── internal/ # Private application code
│ ├── config/
│ │ └── config.go
│ ├── domain/ # Domain layer (entities, value objects)
│ │ ├── order/
│ │ │ ├── order.go
│ │ │ ├── order_item.go
│ │ │ ├── order_status.go
│ │ │ └── repository.go # Repository interface
│ │ └── customer/
│ │ └── customer.go
│ ├── application/ # Application layer (use cases)
│ │ └── order/
│ │ ├── service.go
│ │ ├── create_order.go
│ │ ├── get_order.go
│ │ └── dto.go
│ ├── infrastructure/ # Infrastructure layer
│ │ ├── persistence/
│ │ │ └── postgres/
│ │ │ ├── order_repository.go
│ │ │ └── migrations/
│ │ ├── http/
│ │ │ ├── router.go
│ │ │ ├── middleware/
│ │ │ └── handler/
│ │ │ └── order_handler.go
│ │ └── grpc/
│ │ └── order_server.go
│ └── telemetry/
│ ├── metrics.go
│ ├── tracing.go
│ └── logging.go
├── pkg/ # Public libraries
│ ├── safefile/
│ │ └── safefile.go
│ └── validator/
│ └── validator.go
├── api/ # API definitions
│ ├── openapi/
│ │ └── openapi.yaml
│ └── proto/
│ └── order.proto
├── configs/ # Configuration files
│ ├── config.yaml
│ └── config.example.yaml
├── scripts/ # Build/deploy scripts
│ ├── build.sh
│ └── migrate.sh
├── tests/ # Additional test files
│ ├── e2e/
│ └── integration/
├── Makefile
├── Dockerfile
├── go.mod
├── go.sum
└── README.md
Use complete sentences, start with the name:
// ✅ Good - Package documentation
// Package order provides order management functionality for the
// TelemetryFlow e-commerce platform. It includes entities, repositories,
// and services for creating, updating, and querying orders.
package order
// ✅ Good - Type documentation
// Order represents a customer order in the system. It contains
// all order details including items, status, and timestamps.
type Order struct {
// ID is the unique identifier for the order.
ID string
// CustomerID is the ID of the customer who placed the order.
CustomerID string
// Items contains all items in this order.
Items []OrderItem
// Status represents the current state of the order.
Status OrderStatus
// CreatedAt is when the order was created.
CreatedAt time.Time
}
// ✅ Good - Function documentation
// NewOrder creates a new Order with the given customer ID and items.
// It validates the input and returns an error if the order is invalid.
// The order is created with StatusPending and current timestamp.
func NewOrder(customerID string, items []OrderItem) (*Order, error) {
// implementation
}
// ✅ Good - Method documentation
// AddItem adds an item to the order. It returns an error if the order
// is already completed or cancelled.
func (o *Order) AddItem(item OrderItem) error {
// implementation
}
// ✅ Good - Constant documentation
// OrderStatus represents the current state of an order.
type OrderStatus int
const (
// OrderStatusPending indicates the order is awaiting processing.
OrderStatusPending OrderStatus = iota
// OrderStatusConfirmed indicates the order has been confirmed.
OrderStatusConfirmed
// OrderStatusShipped indicates the order has been shipped.
OrderStatusShipped
// OrderStatusDelivered indicates the order has been delivered.
OrderStatusDelivered
// OrderStatusCancelled indicates the order has been cancelled.
OrderStatusCancelled
)
// ❌ Bad - Poor documentation
// This is the order struct
type Order struct {}
// creates order
func CreateOrder() {}
// order status
const StatusPending = 0Use snake_case for JSON, consistent naming:
// ✅ Good - JSON tags with snake_case
type Order struct {
ID string `json:"id"`
CustomerID string `json:"customer_id"`
OrderNumber string `json:"order_number"`
TotalAmount decimal.Decimal `json:"total_amount"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
// ✅ Good - YAML tags for config
type Config struct {
Server ServerConfig `yaml:"server"`
Database DatabaseConfig `yaml:"database"`
LogLevel string `yaml:"log_level" env:"LOG_LEVEL" default:"info"`
}
// ✅ Good - Multiple tags
type User struct {
ID string `json:"id" db:"user_id" validate:"required,uuid"`
Email string `json:"email" db:"email" validate:"required,email"`
IsActive bool `json:"is_active" db:"is_active"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
// ✅ Good - Omitempty for optional fields
type UpdateOrderRequest struct {
Status *OrderStatus `json:"status,omitempty"`
Notes *string `json:"notes,omitempty"`
ShippingAddr *Address `json:"shipping_address,omitempty"`
}
// ❌ Bad - camelCase in JSON (not API standard)
type Order struct {
ID string `json:"id"`
CustomerId string `json:"customerId"` // Should be customer_id
OrderNum string `json:"orderNum"` // Should be order_num
IsActive bool `json:"isActive"` // Should be is_active
}Use lowercase, hyphen-separated names:
# ✅ Good - Makefile target naming
.PHONY: build run test lint clean
# Build targets
build: ## Build the application
build-linux: ## Build for Linux
build-darwin: ## Build for macOS
build-windows: ## Build for Windows
build-all: ## Build for all platforms
# Run targets
run: ## Run the application
run-dev: ## Run in development mode
run-docker: ## Run in Docker
# Test targets
test: ## Run all tests
test-unit: ## Run unit tests
test-integration: ## Run integration tests
test-e2e: ## Run end-to-end tests
test-coverage: ## Run tests with coverage
# Lint targets
lint: ## Run linter
lint-fix: ## Run linter and fix issues
fmt: ## Format code
fmt-check: ## Check code formatting
vet: ## Run go vet
# Database targets
db-migrate: ## Run database migrations
db-migrate-down: ## Rollback migrations
db-seed: ## Seed database
# Docker targets
docker-build: ## Build Docker image
docker-push: ## Push Docker image
docker-compose-up: ## Start Docker Compose
docker-compose-down: ## Stop Docker Compose
# Clean targets
clean: ## Clean build artifacts
clean-all: ## Clean all generated files
# CI targets
ci-build: ## CI build
ci-test: ## CI test
ci-lint: ## CI lint
# ❌ Bad - Inconsistent naming
Build: # Capitalized
runApplication: # camelCase
test_unit: # snake_case
TestIntegration: # PascalCase| Context | Convention | Example |
|---|---|---|
| TypeScript Variables | camelCase | userId, userName |
| TypeScript Constants | SCREAMING_SNAKE_CASE | MAX_RETRY_ATTEMPTS |
| TypeScript Functions | camelCase | createUser(), findAll() |
| TypeScript Classes | PascalCase | UserService, CreateUserDto |
| Files | kebab-case.type.ts | user.controller.ts |
| Vue Components | PascalCase | UserCard.vue |
| Vue Stores | kebab-case-store | user-store.ts |
| Context | Convention | Example |
|---|---|---|
| Go Package Names | lowercase, single-word | order, config, http |
| Go File Names | snake_case | order_service.go, order_test.go |
| Go Variables (local) | camelCase | orderID, userName |
| Go Variables (exported) | MixedCaps | DefaultTimeout, MaxRetries |
| Go Constants | MixedCaps (NOT SCREAMING) | MaxRetryAttempts, StatusPending |
| Go Functions (exported) | MixedCaps/PascalCase | CreateOrder(), GetByID() |
| Go Functions (unexported) | camelCase | validateOrder(), formatID() |
| Go Interfaces | verb+er suffix | Reader, Writer, OrderRepository |
| Go Structs | MixedCaps | Order, OrderItem, CreateOrderRequest |
| Go Errors | Err prefix | ErrNotFound, ErrInvalidInput |
| Go Tests | Test prefix + underscores | TestOrderService_CreateOrder |
| Go JSON Tags | snake_case | json:"user_id", json:"created_at" |
| Go Makefile Targets | lowercase, hyphen-separated | build-linux, test-unit |
| Context | Convention | Example |
|---|---|---|
| Database Tables | snake_case, plural | users, telemetry_metrics |
| Database Columns | snake_case | user_id, created_at |
| Primary Keys | {entity}_id | user_id, order_id |
| Boolean Columns | is_{property} | is_active, is_deleted |
| Timestamp Columns | {action}_at | created_at, updated_at |
| API Endpoints | kebab-case, plural | /api/v1/users, /api/v1/orders |
| API Query Params | snake_case | ?metric_name=cpu_usage |
| JSON Keys (API) | snake_case | "user_id": "123" |
- 02-DDD-CQRS.md - DDD patterns
- 03-MODULE-STRUCTURE.md - Module organization
- DATABASE-SCHEMA.md - Database schema
- Last Updated: December 26, 2025
- Maintained By: DevOpsCorner Indonesia