You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use dependency injection, avoid singleton pattern abuse
Return DTOs from controllers, never entity instances
// Good - service returns DTO
@Get(':id')asyncfindOne(@Param('id')id: string): Promise<PinDto>{returnthis.pinsService.findOneById(id);}// Bad - service returns entity with ORM internals
@Get(':id')asyncfindOne(@Param('id')id: string): Promise<Pin>{returnthis.pinsRepository.findOne({where: { id }});}
Error Handling
Use exception filters for consistent error responses
Wrap external service calls in try/catch with detailed error contexts
Never expose internal error messages to clients
// Good - typed exceptionif(!pin){thrownewNotFoundException('Pin not found');}// Bad - raw error exposureif(!pin){thrownewError(`Pin ${id} not found`);}
Use 'use client' only when interactivity is required
Fetch data in Server Components, pass as props
// Good - Server ComponentasyncfunctionPinDetail({ id }: {id: string}){constpin=awaitfetchPin(id);return<PinCardpin={pin}/>;}// Bad - unnecessary client component'use client';functionPinDetail({ id }: {id: string}){const[pin,setPin]=useState(null);useEffect(()=>{fetchPin(id).then(setPin);},[id]);return<PinCardpin={pin}/>;}
State Management
Use React state for UI-specific state
Use TanStack Query for server state with caching
Avoid prop drilling; use context sparingly
// Good - cache-aware server stateconst{data: pin, isLoading }=useQuery({queryKey: ['pin',id],queryFn: ()=>fetchPin(id),});// Bad - manual cachingconst[pin,setPin]=useState<Pin|null>(null);useEffect(()=>{fetch(id).then(r=>r.json()).then(setPin);},[id]);
Security
Input Validation
Validate all inputs at the API boundary using class-validator
Rotate secrets quarterly using automated procedures
Envelope encryption for highly sensitive data
DO:
- Store secrets in env files with strict access control
- Use secret references in Kubernetes ConfigMaps/Secrets
- Rotate credentials via External Secrets Operator
DON'T:
- Hardcode credentials in source files
- Share secrets over Slack/email
- Log secrets or authentication tokens
Authentication & Authorization
Use parameterized queries (ORM handles this)
Implement rate limiting per endpoint
Validate JWT/session on every requestNestJS
Use HTTPS in production; enforce HSTS
// Good - decorated guards
@UseGuards(JwtAuthGuard)
@Controller('pins')exportclassPinsController{
@Post()asynccreate(@CurrentUser()user: User){// user is type-safe, from guard}}// Bad - manual auth
@Post()asynccreate(@Req()req){constuser=req.headers.authorization;// deprecated}
CORS Configuration
// Production exampleapp.enableCors({origin: ['https://app.gistpin.io','https://admin.gistpin.io',],credentials: true,methods: ['GET','POST','PUT','PATCH','DELETE'],allowedHeaders: ['Content-Type','Authorization'],});
Observability
Structured Logging
Use structured JSON logging with consistent fields
Include correlation IDs (trace ID, request ID)
Log at appropriate levels (debug, info, warn, error)
# Good - properly tagged resourceresource"aws_db_instance""gistpin" {
identifier="gistpin-${var.environment}"engine="postgres"instance_class="db.r6g.large"storage_encrypted=truetags={
Environment = var.environment
ManagedBy ="Terraform"
Service ="gistpin-backend"
CostCenter ="engineering"
}
}
Database
Query Patterns
Use indexed columns in WHERE clauses
Avoid SELECT * - specify columns explicitly
Use connection pooling (PgBouncer recommended)
Keep transactions short
-- Good - indexed columns, explicit columnsSELECT id, name, location, created_at
FROM pins
WHERE user_id = $1AND deleted_at IS NULLORDER BY created_at DESCLIMIT20;
-- Bad - unindexed column, SELECT *SELECT*FROM pins;
Migrations
Write reversible migrations with both up and down
Test migrations on a copy of production data
Avoid non-transactional DDL in production
-- Good - reversible migration-- UpCREATEINDEXCONCURRENTLY pins_user_id_idx ON pins (user_id);
-- DownDROPINDEX CONCURRENTLY pins_user_id_idx;
Data Integrity
Use database constraints (FOREIGN KEY, CHECK, UNIQUE)
Prevent SQL injections through ORM usage
Implement soft deletes using deleted_at timestamps
Database-level IDs (UUID or SERIAL), not client-generated
API Design
REST Conventions
Use nouns for resources (/pins, /users)
Version APIs explicitly (/api/v1/pins)
Return appropriate HTTP status codes
Consistent error response format
// Standard error response{"success": false,"error": {"code": "PIN_NOT_FOUND","message": "The requested pin does not exist","details": {"pinId": "abc123","userId": "user456"},"traceId": "abc123def456"}}
# Post-Mortem: [Incident Title]-**Date**: YYYY-MM-DD
-**Severity**: P1 / P2 / P3
-**Duration**: X hours Y minutes
-**Author**: Name
## Summary
Brief description of the incident.
## Timeline- HH:MM - Event observed
- HH:MM - Investigation started
- HH:MM - Root cause identified
- HH:MM - Resolution applied
## Root Cause
Technical explanation of what went wrong.
## Impact- Affected users: X%
- Duration: X minutes
- Data loss: None / Limited
## Action Items| Action | Owner | Due Date | Status ||--------|-------|----------|--------|| Add alert for X |@engineer| YYYY-MM-DD | TODO |