You're building a microservices platform with NestJS. How would you implement distributed tracing and observability across services to monitor request flows, identify bottlenecks, and troubleshoot production issues?
Implement OpenTelemetry with NestJS interceptors for automatic span creation, use correlation IDs in headers, integrate with DataDog/Jaeger for visualization, add custom metrics for business logic, and implement structured logging with trace context
Use Azure Application Insights SDK with custom telemetry tracking, implement correlation IDs using AsyncLocalStorage, add custom dimensions for business context, and configure sampling for high-volume scenarios
Implement distributed tracing using Zipkin or Jaeger with NestJS middleware, use W3C Trace Context for propagation, add custom spans for business operations, and integrate with APM tools like New Relic or Dynatrace
Design an event-driven architecture using Azure Service Bus that ensures exactly-once message processing, handles dead-letter queues, and implements retry policies with exponential backoff for failed messages.
Enable sessions for message ordering, implement idempotency keys in message handlers, configure dead-letter queues with max delivery count, use exponential backoff retry policies, and implement message deduplication with distributed locks or database constraints
Use Azure Service Bus sessions with message correlation, implement transactional outbox pattern for reliability, configure retry policies with circuit breaker, and use competing consumers pattern for scalability
Implement saga pattern for distributed transactions, use message deduplication with Redis or database unique constraints, configure poison message handling, and add monitoring for queue metrics
Your NestJS application needs to handle 10,000 concurrent WebSocket connections for real-time updates. How do you architect this for horizontal scalability while maintaining connection state?
Implement Redis pub/sub for cross-server communication, use sticky sessions with load balancer, store connection metadata in Redis, implement heartbeat mechanisms, and consider Socket.IO with Redis adapter or Azure SignalR Service for auto-scaling
Use Azure SignalR Service for managed WebSocket scaling, implement backplane with Redis or Service Bus, use connection grouping for targeted messaging, and implement reconnection logic with exponential backoff
Deploy Socket.IO with Redis adapter for horizontal scaling, implement room-based message distribution, use connection pooling and heartbeats, and add monitoring for connection metrics
Design a GraphQL schema and resolvers in NestJS that implements N+1 query problem prevention, field-level authorization, query complexity analysis, and implements DataLoader for batch loading.
Use DataLoader for batching and caching, implement query complexity analysis with graphql-query-complexity, add field-level guards/decorators for authorization, use MongoDB aggregation pipelines, and implement persisted queries for production
Implement N+1 prevention using DataLoader with custom batch functions, use GraphQL Yoga or Apollo Server with built-in caching, add depth limiting and query cost analysis, and implement field-level resolvers with optimized database queries
Use batched resolvers with DataLoader, implement query whitelisting or persisted queries, add authorization directives for field-level security, and optimize database queries with proper indexes and aggregation
Implement a MongoDB aggregation pipeline for a complex reporting query that joins multiple collections, performs grouping, filtering, and needs to handle millions of documents efficiently.
Design compound indexes matching query patterns, use $lookup with pipeline optimization, implement $facet for multiple aggregations, add $match early in pipeline, use $project to limit fields, consider materialized views or pre-aggregated collections for frequent queries
Create aggregation pipelines with $match at start for filtering, use $lookup with localField/foreignField for joins, implement $group with accumulators, add indexes for sort operations, and consider read preferences for scaling
Optimize pipeline with early $match stages, use $addFields and $project for transformations, implement $bucket or $bucketAuto for data distribution, add appropriate indexes, and consider using change streams for real-time updates
Explain how you would implement a CI/CD pipeline for a NestJS monorepo using GitHub Actions, with trunk-based development, automated testing, and deployment to Azure with zero-downtime.
Use Nx for monorepo management with affected commands, implement GitHub Actions workflows for PR checks and deployments, use feature flags for gradual rollouts, implement blue-green deployment on Azure, run integration tests in staging environment, and use semantic versioning with automated releases
Implement trunk-based development with short-lived feature branches, use GitHub Actions with matrix builds for parallel testing, deploy using Azure App Service slots for zero-downtime, implement automated rollback on failures, and use Dependabot for dependency updates
Use Nx or Turborepo for monorepo with caching, implement CI pipeline with linting/testing/building stages, use Docker for consistent environments, deploy to Azure Kubernetes Service with rolling updates, and implement canary deployments for gradual rollout
How do you implement API versioning in NestJS for a production system where you need to maintain backward compatibility while introducing breaking changes?
Use URI versioning (/v1/, /v2/), implement version-specific controllers and DTOs, use decorators for version routing, maintain separate Swagger documentation per version, implement deprecation warnings in headers, and use feature flags for gradual migration
Implement header-based versioning (Accept: application/vnd.api.v2+json), use content negotiation for version selection, maintain backward compatibility with adapters, add sunset headers for deprecated versions, and use API gateway for version routing
Use semantic versioning with URI paths, implement version-specific modules in NestJS, create version mappers for data transformation, document breaking changes clearly, and provide migration guides for clients
Design a caching strategy for a NestJS API that uses Redis, handles cache invalidation across microservices, and implements cache-aside pattern with proper error handling.
Implement cache-aside pattern with decorators, use Redis pub/sub for cross-service invalidation, set appropriate TTLs based on data volatility, implement circuit breaker for Redis failures, use cache warming for critical data, and add cache metrics monitoring
Use multi-layer caching with memory cache for hot data and Redis for distributed cache, implement cache invalidation using tags or keys patterns, add fallback to database on cache miss, monitor cache hit rates, and use cache stampede prevention
Implement write-through or write-behind caching strategies, use Redis Cluster for high availability, add cache versioning for safe updates, implement LRU eviction policies, and use cache warming during deployment
How would you implement authentication and authorization in a microservices architecture using JWT tokens, refresh tokens, and role-based access control (RBAC)?
Implement JWT with short-lived access tokens and long-lived refresh tokens, use NestJS guards for route protection, implement RBAC with custom decorators, store refresh tokens securely in database, use API gateway for token validation, and implement token rotation and revocation mechanisms
Use OAuth2/OIDC with authorization code flow, implement JWT validation with public key verification, use claims-based authorization with custom claims, store refresh tokens with encryption, and implement token introspection for validation
Implement JWT authentication with RS256 signing, use refresh token rotation for security, add role-based and permission-based authorization, implement rate limiting per user, and use API gateway or service mesh for centralized auth
Explain how you would handle database migrations in a MongoDB-based microservices architecture where services are deployed independently and need to maintain data consistency.
Use migration tools like migrate-mongo, implement backward-compatible schema changes, use versioned data models, implement dual-write pattern during transitions, maintain migration scripts in version control, and test migrations in staging environment first
Implement schema versioning with document version fields, use expand-contract pattern for migrations, create migration scripts with rollback capability, test migrations with production-like data, and document migration procedures
Use change streams for data synchronization, implement gradual schema migration with application support for multiple versions, add migration status tracking, use blue-green deployment for database changes, and implement automated testing for migrations
What are the key differences between NestJS modules, providers, and controllers? How do you organize a large-scale application?
Modules organize code into cohesive blocks, Controllers handle HTTP requests and routing, Providers are services with dependency injection. For large apps: use feature modules, shared modules, core module pattern, implement domain-driven design with bounded contexts
Modules encapsulate related functionality with imports/exports, Controllers define API endpoints and handle HTTP layer, Providers contain business logic with @Injectable. Organize with feature-based structure, separate core/shared/feature modules, and use dynamic modules for configuration
Modules group related components and services, Controllers route requests to appropriate handlers, Providers are injected dependencies (services, repositories). Structure large apps with vertical slicing by features, horizontal layers (domain/application/infrastructure), and shared libraries
Explain the difference between useEffect, useLayoutEffect, and useCallback hooks. When would you use each one?
useEffect runs after paint (async), useLayoutEffect runs before paint (sync - for DOM measurements), useCallback memoizes functions. Use useEffect for data fetching, useLayoutEffect for DOM manipulation/measurements, useCallback to prevent unnecessary re-renders of child components
useEffect for side effects after render (API calls, subscriptions), useLayoutEffect for synchronous DOM reads/writes before paint (scroll position, animations), useCallback to memoize callback functions and prevent child re-renders when passed as props
useEffect is async and doesn't block painting, useLayoutEffect is synchronous and blocks painting (use for measuring DOM), useCallback returns memoized function to optimize performance when passing callbacks to optimized child components
How would you optimize a React application that renders a large list (10,000+ items) with complex data and user interactions?
Implement virtualization with react-window or react-virtualized, use React.memo for list items, implement pagination or infinite scroll, use useCallback for event handlers, optimize re-renders with proper key props, consider web workers for heavy computations
Use windowing libraries (react-virtualized, react-window) to render only visible items, implement useMemo for expensive calculations, add debouncing for search/filter, use React.memo with custom comparison, and consider pagination with cursor-based approach
Implement virtual scrolling with TanStack Virtual, optimize with React.memo and useMemo, use intersection observer for lazy loading, add request animation frame for smooth updates, and move heavy processing to web workers
Explain React's Context API and when you should use it vs. prop drilling vs. state management libraries like Redux or Zustand.
Context API avoids prop drilling for component trees, use for theme/auth/locale. Prop drilling is fine for 2-3 levels. Use Redux/Zustand for complex state with many updates, time-travel debugging, or when context causes performance issues due to re-renders
Use Context API for global state that doesn't change often (theme, auth, i18n), prop drilling for simple parent-child communication, and Redux/Zustand/Jotai for complex application state with frequent updates, middleware needs, or DevTools integration
Context API for dependency injection and simple global state, prop drilling when intermediate components need the data, state management libraries (Redux, Zustand, Recoil) for complex state logic, async state management, or when context causes performance bottlenecks
How do you implement error boundaries in React, and what are their limitations? How would you handle async errors?
Error boundaries catch errors in render, lifecycle methods, and constructors using componentDidCatch. They don't catch async errors, event handlers, or server-side rendering errors. For async: use try-catch in async functions, implement global error handling, use React Query error handlers
Error boundaries use componentDidCatch and getDerivedStateFromError for error handling. Limitations: don't catch event handler errors, async code, SSR errors. Handle async errors with try-catch, use error tracking services (Sentry), and implement fallback UI
Implement error boundaries with class components using componentDidCatch. They catch render errors but not async, event handlers, or server errors. For comprehensive error handling: combine with try-catch, window.onerror, unhandledrejection events, and error monitoring tools
What is the Virtual DOM in React and how does it improve performance?
Design a GraphQL schema and resolver architecture for a complex e-commerce system with nested relationships, including products, categories, reviews, users, and orders. How would you handle the N+1 query problem and implement efficient data loading?
Implement DataLoader for batching and caching database queries, use field resolvers with context sharing, design schema with proper types and interfaces, implement pagination with cursor-based approach, use query complexity analysis to prevent expensive queries, add depth limiting, and leverage GraphQL subscriptions for real-time updates on order status
Use DataLoader for N+1 prevention with batching, implement connection pattern for pagination, add query cost analysis and depth limiting, design normalized schema with proper relationships, use field-level caching, and implement subscriptions with PubSub for real-time features
Implement batching with DataLoader, use relay-style pagination with connections, add query complexity limits and depth restrictions, design schema with clear separation of concerns, implement caching strategies per field, and use GraphQL subscriptions for order status updates
How would you implement authentication, authorization, and rate limiting in a GraphQL API using NestJS? Include considerations for mutations, subscriptions, and field-level permissions.
Use NestJS Guards for authentication with JWT tokens in GraphQL context, implement custom directives (@auth, @hasRole) for field-level authorization, use ThrottlerGuard with custom key generation for rate limiting per user/IP, implement complexity-based rate limiting for expensive queries, secure subscriptions with connection authentication, and use context to pass user permissions through resolver chain
Implement authentication using Guards with JWT validation in GraphQL context, create custom schema directives for authorization (@authenticated, @hasPermission), add rate limiting with graphql-rate-limit or custom implementation, use query complexity analysis to prevent abuse, secure WebSocket subscriptions with connection params
Use NestJS authentication guards in GraphQL resolvers, implement directive-based authorization for fields/queries, add rate limiting per resolver or globally with decorators, implement query depth and complexity limits, secure subscriptions with token in connection initialization, and pass auth context through resolver chain