Skip to main content
    January 23, 202650 min readBackend Development

    The Backend Questions That Stumped Me at Meta, Uber, and Stripe

    After 300+ backend interviews and building systems that handle millions of requests, I've learned that interviews aren't about memorizing HTTP status codes—they're about demonstrating you can design resilient, scalable systems.

    Backend developer working on server infrastructure with multiple screens showing APIs, databases, and system architecture

    My worst backend interview was at a unicorn startup. The interviewer asked, "Design an API for a high-traffic social media feed." I jumped straight into endpoint design. Big mistake. They interrupted: "That's fine, but how do you handle 10 million users? What about caching? Database sharding? Rate limiting?"

    That moment taught me backend interviews aren't about crafting perfect JSON responses. They're about thinking through the entire system—from the first HTTP request to the database query, from caching strategies to failover mechanisms. The best backend engineers don't just write APIs; they architect systems that don't break under pressure.

    This guide covers 40 questions that separate junior backend developers from senior engineers. Each answer reflects real-world experience building systems at scale, complete with trade-offs, gotchas, and the reasoning that interviewers want to hear.

    What Backend Interviewers Evaluate

    • API Design: RESTful principles, versioning, error handling, documentation
    • Database Mastery: SQL optimization, NoSQL trade-offs, transaction handling
    • System Architecture: Microservices, caching layers, message queues
    • Performance & Scale: Bottleneck identification, monitoring, optimization
    • Security Mindset: Authentication, authorization, data protection, threat modeling

    REST APIs & Web Services (Questions 1-10)

    1. What are the key principles of RESTful API design?

    Tests fundamental understanding of REST architecture

    Answer:

    • Stateless: Each request contains all information needed to process it
    • Resource-based URLs: Use nouns, not verbs (/users/123, not /getUser/123)
    • HTTP Methods: GET (read), POST (create), PUT (update), DELETE (remove)
    • Standard Status Codes: 200 (success), 201 (created), 400 (bad request), 404 (not found)
    • Uniform Interface: Consistent data formats and naming conventions
    • HATEOAS: Include links to related resources in responses

    2. How do you handle API versioning?

    Tests understanding of backward compatibility and API evolution

    Answer:

    URL Versioning: /v1/users, /v2/users (most common, clear and cacheable)

    Header Versioning: Accept: application/vnd.api+json;version=1

    Query Parameter: /users?version=1 (simple but can clutter URLs)

    # Best practice: URL versioning with semantic versioning

    GET /v2/users/123

    Accept: application/json

    Strategy: Maintain 2-3 versions maximum, deprecate gracefully with clear timelines.

    3. Explain the difference between PUT and PATCH.

    Answer:

    • PUT: Idempotent, replaces entire resource. Send full object even if updating one field.
    • PATCH: Partial update, send only changed fields. More network efficient.
    • Idempotency: Both should be idempotent (same result if called multiple times)
    • Use PUT for: Complete resource replacement
    • Use PATCH for: Partial updates, especially for large resources

    4. How do you implement API rate limiting?

    Answer:

    Token Bucket: Refill tokens at fixed rate, consume on requests

    Sliding Window: Track requests in rolling time window

    Fixed Window: Simple counter reset at intervals

    # Implementation with Redis

    INCR user:123:requests:2026-01-23-14

    EXPIRE user:123:requests:2026-01-23-14 3600

    # Return 429 if count > limit

    Headers: Include X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset

    5. What's the difference between authentication and authorization?

    Answer:

    • Authentication: "Who are you?" - Verifying identity (login, JWT token validation)
    • Authorization: "What can you do?" - Checking permissions (roles, RBAC)
    • Example: JWT token authenticates user, RBAC authorizes specific actions
    • Security principle: Always authenticate first, then authorize specific actions
    • Implementation: Middleware handles auth, business logic handles authorization

    6. How do you handle API errors and status codes?

    Answer:

    2xx Success: 200 (OK), 201 (Created), 204 (No Content)

    4xx Client Errors: 400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), 422 (Validation Error)

    5xx Server Errors: 500 (Internal Error), 502 (Bad Gateway), 503 (Service Unavailable)

    # Consistent error response format

    {

    "error": "VALIDATION_FAILED",

    "message": "Invalid email format",

    "details": [{"field": "email", "code": "INVALID_FORMAT"}

    }

    7. What is CORS and how do you configure it?

    Answer:

    CORS (Cross-Origin Resource Sharing): Mechanism allowing web pages to access resources from different domains.

    Same-Origin Policy: Browsers block cross-origin requests by default for security

    Preflight Request: OPTIONS request for complex requests (POST with JSON)

    # Express.js CORS configuration

    app.use(cors({

    origin: ['https://myapp.com'],

    credentials: true,

    methods: ['GET', 'POST', 'PUT', 'DELETE']

    }))

    8. How do you implement pagination in APIs?

    Answer:

    Offset-based: ?page=2&limit=20 (simple but inefficient for large datasets)

    Cursor-based: ?after=eyJpZCI6MTIzfQ&limit=20 (better performance, consistent results)

    # Cursor-based pagination response

    {

    "data": [...],

    "pagination": {

    "has_more": true,

    "next_cursor": "eyJpZCI6MTQ1fQ"

    }

    }

    Headers: Include Link header for navigation (GitHub style)

    9. What are webhooks and how do you implement them securely?

    Answer:

    Webhooks: HTTP callbacks triggered by events, enabling real-time communication

    Security measures:

    • HTTPS only
    • Signature verification (HMAC-SHA256)
    • Timestamp validation (prevent replay attacks)
    • IP whitelisting when possible

    # Webhook signature verification

    const signature = req.headers['x-webhook-signature']

    const payload = JSON.stringify(req.body)

    const expected = crypto.createHmac('sha256', secret)

    .update(payload).digest('hex')

    10. How do you document APIs effectively?

    Answer:

    • OpenAPI/Swagger: Industry standard, interactive documentation
    • Include examples: Request/response samples for all endpoints
    • Error scenarios: Document all possible error responses
    • Authentication: Clear auth flow documentation
    • Rate limits: Document limits and headers
    • SDKs: Provide client libraries for popular languages
    • Changelog: Track API changes and deprecations

    Database Design & Optimization (Questions 11-20)

    11. Explain database normalization and when you might denormalize.

    Tests database design fundamentals and trade-off understanding

    Answer:

    Normalization: Reducing data redundancy by organizing into separate tables

    • 1NF: Atomic values, no repeating groups
    • 2NF: No partial dependencies on composite keys
    • 3NF: No transitive dependencies

    When to denormalize: Read-heavy workloads, complex joins affecting performance, data warehousing scenarios

    Trade-offs: Normalization reduces storage and update complexity; denormalization improves read performance

    12. How do you optimize slow database queries?

    Answer:

    1. Analyze query execution plan (EXPLAIN in PostgreSQL/MySQL)
    2. Add appropriate indexes on WHERE, JOIN, ORDER BY columns
    3. Avoid SELECT * - only fetch needed columns
    4. Optimize WHERE clauses - put most selective conditions first
    5. Consider query restructuring - break complex queries into simpler ones
    6. Use query caching for repeated queries

    # Example optimization

    -- Slow: table scan

    SELECT * FROM users WHERE email = 'user@example.com'


    -- Fast: with index on email column

    CREATE INDEX idx_users_email ON users(email)

    13. What's the difference between SQL and NoSQL databases?

    Answer:

    SQL Databases:

    • • ACID compliance
    • • Fixed schema
    • • Complex relationships
    • • Strong consistency
    • • Vertical scaling
    • • Examples: PostgreSQL, MySQL

    NoSQL Databases:

    • • Flexible schema
    • • Horizontal scaling
    • • Eventual consistency
    • • High performance reads
    • • Document/Key-value storage
    • • Examples: MongoDB, Redis, DynamoDB

    When to use: SQL for complex transactions, NoSQL for high-scale, flexible data

    14. Explain database transactions and ACID properties.

    Answer:

    ACID Properties:

    • Atomicity: All operations succeed or all fail (no partial updates)
    • Consistency: Database remains in valid state after transaction
    • Isolation: Concurrent transactions don't interfere with each other
    • Durability: Committed changes persist even after system failure

    # Example transaction

    BEGIN;

    UPDATE accounts SET balance = balance - 100 WHERE id = 1;

    UPDATE accounts SET balance = balance + 100 WHERE id = 2;

    COMMIT;

    15. How do you handle database connection pooling?

    Answer:

    Connection pooling: Reuse database connections to reduce overhead

    Benefits: Faster response times, reduced resource usage, better concurrency control

    Configuration considerations:

    • Pool size: Balance between resource usage and concurrency
    • Connection timeout: How long to wait for available connection
    • Idle timeout: When to close unused connections
    • Health checks: Validate connections before use

    # Example with Node.js pg-pool

    const pool = new Pool({

    max: 20, // maximum pool size

    idleTimeoutMillis: 30000,

    connectionTimeoutMillis: 2000

    })

    16. What are database indexes and how do they work?

    Answer:

    Indexes: Data structures that improve query performance by creating shortcuts to data

    Types:

    • B-tree: Default, good for equality and range queries
    • Hash: Fast for equality lookups only
    • Bitmap: Efficient for low-cardinality data
    • Partial: Index subset of rows based on condition

    Trade-offs: Faster reads vs slower writes, additional storage overhead

    Best practices: Index frequently queried columns, avoid over-indexing, monitor index usage

    17. How do you implement database migrations safely?

    Answer:

    Safe migration practices:

    1. Backward compatibility: New code works with old schema
    2. Forward compatibility: Old code works with new schema
    3. Incremental changes: Small, reversible migrations
    4. Test on staging: Identical environment testing
    5. Rollback plan: Always have a rollback strategy
    6. Zero-downtime: Avoid locking operations during peak hours

    # Example safe column addition

    -- Step 1: Add nullable column

    ALTER TABLE users ADD COLUMN phone VARCHAR(20);

    -- Step 2: Deploy code that uses new column

    -- Step 3: Backfill data if needed

    -- Step 4: Make column NOT NULL if required

    18. What is database sharding and when would you use it?

    Answer:

    Sharding: Horizontal partitioning of data across multiple databases

    When to shard: Single database can't handle load, data size exceeds single machine capacity

    Sharding strategies:

    • Range-based: Partition by data range (user_id 1-1000, 1001-2000)
    • Hash-based: Use hash function on key (user_id % 4)
    • Directory-based: Lookup service maps keys to shards

    Challenges: Cross-shard queries, rebalancing, increased complexity

    Alternatives: Read replicas, vertical partitioning, caching layers

    19. Explain the CAP theorem and its implications.

    Answer:

    CAP Theorem: You can only guarantee 2 of 3 properties in distributed systems:

    • Consistency: All nodes see same data at same time
    • Availability: System remains operational
    • Partition tolerance: System continues despite network failures

    Real-world examples:

    • CA: Traditional RDBMS (not partition tolerant)
    • CP: MongoDB, Redis (sacrifice availability for consistency)
    • AP: DynamoDB, Cassandra (eventual consistency)

    Practical implication: In network partitions, choose consistency or availability

    20. How do you backup and recover databases effectively?

    Answer:

    Backup strategies:

    • Full backups: Complete database snapshot (weekly)
    • Incremental: Only changed data since last backup (daily)
    • Point-in-time: Transaction log backups for specific recovery points
    • Hot vs Cold: Online backups vs offline with downtime

    3-2-1 Rule: 3 copies of data, 2 different media types, 1 offsite

    Recovery considerations: RTO (Recovery Time Objective), RPO (Recovery Point Objective)

    Testing: Regularly test backup restoration process

    Caching & Performance (Questions 21-27)

    21. Explain different caching strategies and when to use them.

    Tests understanding of caching patterns and trade-offs

    Answer:

    Cache-Aside (Lazy Loading): Application manages cache

    • Read: Check cache → if miss, fetch from DB and cache

    • Write: Update DB, invalidate cache

    Write-Through: Write to cache and DB simultaneously

    • Consistent but slower writes

    Write-Behind (Write-Back): Write to cache first, DB later

    • Faster writes but risk of data loss

    # Cache-aside example

    data = cache.get(key)

    if (!data) {

    data = database.get(key)

    cache.set(key, data, ttl)

    }

    22. How do you handle cache invalidation?

    Answer:

    "There are only two hard things in Computer Science: cache invalidation and naming things"

    Strategies:

    • TTL (Time To Live): Automatic expiration after fixed time
    • Event-based: Invalidate on data updates (pub/sub pattern)
    • Tag-based: Group related cache entries with tags
    • Manual: Explicit invalidation in business logic

    # Event-based invalidation with Redis

    // On user update

    await updateUser(userId, data)

    await cache.del(`user:${ userId }`)

    await pubsub.publish('user:updated', userId)

    23. What's the difference between Redis and Memcached?

    Answer:

    Redis:

    • • Rich data structures (sets, hashes, lists)
    • • Persistence options (RDB, AOF)
    • • Pub/Sub messaging
    • • Lua scripting
    • • Single-threaded
    • • Built-in replication

    Memcached:

    • • Simple key-value storage
    • • No persistence
    • • Multi-threaded
    • • Lower memory overhead
    • • Simpler architecture
    • • Better for simple caching

    Choose Redis for: Complex data structures, persistence. Memcached for: Simple, high-performance caching.

    24. How do you implement distributed caching?

    Answer:

    Distributed caching patterns:

    • Shared Cache: Single cache cluster accessed by all app instances
    • Replicated Cache: Each app instance has copy of cache data
    • Partitioned Cache: Cache data distributed across multiple nodes

    Consistent hashing: Distribute keys evenly, minimize rehashing when nodes change

    # Consistent hashing example

    const hash = hashFunction(key)

    const nodeIndex = hash % nodes.length

    const cacheNode = nodes[nodeIndex]

    Challenges: Network latency, cache coherency, failover handling

    25. What is CDN and how does it improve performance?

    Answer:

    CDN (Content Delivery Network): Geographically distributed servers that cache content closer to users

    Benefits:

    • • Reduced latency (geographic proximity)
    • • Lower bandwidth costs
    • • Improved availability and redundancy
    • • DDoS protection
    • • Reduced origin server load

    Best practices:

    • • Set appropriate cache headers (Cache-Control, ETag)
    • • Use versioned URLs for cache busting
    • • Optimize cache hit ratio
    • • Monitor cache performance metrics

    26. How do you measure and improve API performance?

    Answer:

    Key metrics:

    • Latency: Response time (p50, p95, p99 percentiles)
    • Throughput: Requests per second
    • Error rate: Percentage of failed requests
    • Resource utilization: CPU, memory, database connections

    Optimization techniques:

    • • Database query optimization
    • • Implement caching layers
    • • Use compression (gzip)
    • • Connection pooling
    • • Async processing for heavy operations
    • • Load balancing and horizontal scaling

    27. What are the common causes of memory leaks in backend applications?

    Answer:

    Common causes:

    • Unclosed resources: Database connections, file handles, HTTP connections
    • Event listeners: Not removing event handlers
    • Global variables: Accumulating data in global scope
    • Circular references: Objects referencing each other
    • Caches without limits: Unbounded cache growth

    # Prevention example

    try {

    const connection = await pool.connect()

    // ... use connection

    } finally {

    connection?.release() // Always cleanup

    }

    Detection: Memory monitoring, profiling tools, heap dumps

    Security & Authentication (Questions 28-33)

    28. How do you implement JWT authentication securely?

    Tests security best practices for token-based authentication

    Answer:

    JWT Security best practices:

    • Short expiration times: 15-30 minutes for access tokens
    • Use refresh tokens: Longer-lived, revocable tokens
    • Strong secret keys: Use cryptographically secure random keys
    • HTTPS only: Never send JWTs over HTTP
    • Secure storage: HttpOnly cookies, not localStorage
    • Validate claims: Check issuer, audience, expiration

    # Secure JWT implementation

    const token = jwt.sign(

    { userId, email },

    process.env.JWT_SECRET,

    { expiresIn: '15m', issuer: 'myapp' }

    )

    29. What are the common security vulnerabilities in web applications?

    Answer (OWASP Top 10):

    1. Injection: SQL, NoSQL, command injection - use parameterized queries
    2. Broken Authentication: Weak passwords, session management - implement MFA, secure sessions
    3. Sensitive Data Exposure: Unencrypted data - encrypt at rest and in transit
    4. XML External Entities (XXE): XML processing vulnerabilities - disable external entities
    5. Broken Access Control: Authorization flaws - implement principle of least privilege
    6. Security Misconfiguration: Default configs - secure defaults, regular updates
    7. Cross-Site Scripting (XSS): Input validation - sanitize user input, CSP headers
    8. Insecure Deserialization: Untrusted data - validate and sanitize serialized objects
    9. Known Vulnerabilities: Outdated dependencies - regular security updates
    10. Insufficient Logging: Poor monitoring - comprehensive audit trails

    30. How do you protect against SQL injection attacks?

    Answer:

    Prevention techniques:

    • Parameterized queries: Use prepared statements with parameters
    • Stored procedures: When properly implemented
    • Input validation: Whitelist allowed characters
    • Principle of least privilege: Database user with minimal permissions
    • Escape special characters: When parameterized queries aren't possible

    # Vulnerable code

    const query = `SELECT * FROM users WHERE email = '${ email }'`


    # Secure code

    const query = 'SELECT * FROM users WHERE email = $1'

    const result = await client.query(query, [email])

    31. How do you implement secure password storage?

    Answer:

    Password hashing best practices:

    • Use bcrypt, scrypt, or Argon2: Slow hashing algorithms with salt
    • Never store plaintext: Hash passwords before storage
    • Unique salts: Different salt per password
    • High work factor: Adjust cost parameter for security vs performance
    • Password policies: Minimum length, complexity requirements

    # Secure password hashing

    const bcrypt = require('bcrypt')

    const saltRounds = 12


    // Hash password

    const hashedPassword = await bcrypt.hash(password, saltRounds)


    // Verify password

    const isValid = await bcrypt.compare(password, hashedPassword)

    32. What is CORS and how do you configure it securely?

    Answer:

    CORS (Cross-Origin Resource Sharing): Browser security feature that restricts cross-origin HTTP requests

    Secure configuration:

    • Specific origins: Never use * in production
    • Limit methods: Only allow necessary HTTP methods
    • Control headers: Restrict allowed and exposed headers
    • Credentials handling: Be careful with Access-Control-Allow-Credentials

    # Secure CORS configuration

    app.use(cors({

    origin: ['https://myapp.com', 'https://admin.myapp.com'],

    methods: ['GET', 'POST', 'PUT', 'DELETE'],

    credentials: true,

    optionsSuccessStatus: 200

    }))

    33. How do you implement role-based access control (RBAC)?

    Answer:

    RBAC Components:

    • Users: Individual accounts
    • Roles: Groups of permissions (admin, editor, viewer)
    • Permissions: Specific actions (read, write, delete)
    • Resources: Objects being protected

    # RBAC middleware example

    const requireRole = (roles) => async (req, res, next) => {

    const userRoles = await getUserRoles(req.user.id)

    const hasPermission = roles.some(role =>

    userRoles.includes(role))

    if (!hasPermission) return res.status(403).json(...)

    next()

    }

    Best practices: Principle of least privilege, role hierarchies, audit logs

    Microservices & System Design (Questions 34-40)

    34. What are microservices and when should you use them?

    Tests understanding of distributed architecture patterns

    Answer:

    Microservices: Architectural pattern where applications are built as independent, loosely coupled services

    Benefits:

    • • Independent deployment and scaling
    • • Technology diversity
    • • Team autonomy
    • • Fault isolation

    Challenges:

    • • Distributed system complexity
    • • Network latency and reliability
    • • Data consistency
    • • Monitoring and debugging

    When to use: Large teams, complex domains, need for different scaling patterns. Start with monolith for small teams/simple domains.

    35. How do you handle communication between microservices?

    Answer:

    Synchronous communication:

    • REST APIs: HTTP-based, stateless, widely supported
    • GraphQL: Single endpoint, flexible queries
    • gRPC: High-performance, type-safe, HTTP/2

    Asynchronous communication:

    • Message queues: RabbitMQ, Apache Kafka, AWS SQS
    • Event streaming: Pub/sub patterns, event sourcing
    • Service mesh: Istio, Linkerd for service-to-service communication

    Best practices: Circuit breakers, retries with backoff, timeouts, idempotency

    36. What is the Circuit Breaker pattern?

    Answer:

    Circuit Breaker: Design pattern that prevents cascading failures in distributed systems

    States:

    • Closed: Normal operation, requests pass through
    • Open: Failures detected, requests fail fast
    • Half-Open: Limited requests to test if service recovered

    # Circuit breaker implementation concept

    if (circuitBreaker.state === 'OPEN') {

    throw new Error('Circuit breaker is OPEN')

    }

    try {

    const result = await externalService.call()

    circuitBreaker.recordSuccess()

    return result

    } catch (error) {

    circuitBreaker.recordFailure()

    throw error

    }

    Benefits: Prevents cascade failures, improves system resilience, provides fallback mechanisms

    37. How do you handle distributed transactions?

    Answer:

    Two-Phase Commit (2PC): Coordinator ensures all participants commit or abort

    • • Phase 1: Vote to commit/abort
    • • Phase 2: Commit or abort based on votes
    • • Problems: Blocking protocol, single point of failure

    Saga Pattern (Preferred): Sequence of local transactions with compensating actions

    • Choreography: Events trigger next steps
    • Orchestration: Central coordinator manages flow

    # Saga example: Order processing

    1. Reserve inventory

    2. Charge payment

    3. Ship order

    # If payment fails: Release inventory

    Eventual Consistency: Accept temporary inconsistency for better availability

    38. What are message queues and when do you use them?

    Answer:

    Message Queues: Asynchronous communication mechanism between services

    Benefits:

    • • Decoupling of services
    • • Reliability (persistence, acknowledgments)
    • • Scalability (handle traffic spikes)
    • • Fault tolerance

    Use cases:

    • • Background job processing
    • • Event-driven architecture
    • • Load balancing across workers
    • • Handling traffic spikes

    Popular solutions: RabbitMQ (feature-rich), Apache Kafka (high-throughput), AWS SQS (managed), Redis Pub/Sub (simple)

    39. How do you implement service discovery in microservices?

    Answer:

    Service Discovery: Mechanism for services to find and communicate with each other

    Patterns:

    • Client-side discovery: Client queries service registry (Eureka, Consul)
    • Server-side discovery: Load balancer handles discovery (AWS ELB, Kubernetes)

    Service Registry: Database of available service instances

    • • Health checks
    • • Load balancing
    • • Failover handling

    # Kubernetes service discovery

    http://user-service.default.svc.cluster.local:8080


    # Consul service discovery

    const services = await consul.health.service('user-service')

    40. How do you design a system that can handle millions of users?

    Answer:

    Scalability principles:

    Horizontal scaling:

    • • Load balancers
    • • Stateless services
    • • Auto-scaling groups
    • • Database sharding

    Performance optimization:

    • • Multi-level caching (CDN, Redis, in-memory)
    • • Database optimization (indexes, read replicas)
    • • Async processing (queues, workers)
    • • Connection pooling

    Architecture patterns:

    • • Microservices for independent scaling
    • • Event-driven architecture
    • • CQRS (Command Query Responsibility Segregation)
    • • Data partitioning strategies

    Monitoring & reliability: Comprehensive logging, metrics, alerting, circuit breakers, graceful degradation

    Ready to Ace Your Backend Interview?

    Get personalized practice with LastRound AI's interview copilot. Practice these questions with real-time feedback and expert guidance.

    The Backend Engineering Mindset

    After years of backend development and hundreds of interviews, I've learned that the best backend engineers share common traits:

    ✓ What Great Engineers Show:

    • • Systems thinking - understanding how components interact
    • • Performance awareness - always considering scalability
    • • Security mindset - building defense in depth
    • • Reliability focus - designing for failure scenarios
    • • Trade-off analysis - explaining why you chose approach A over B
    • • Monitoring culture - you can't manage what you don't measure

    ❌ Common Interview Mistakes:

    • • Jumping to solutions without understanding requirements
    • • Ignoring error handling and edge cases
    • • Over-engineering simple problems
    • • Not considering operational aspects (monitoring, debugging)
    • • Focusing only on happy path scenarios
    • • Not discussing scalability and performance implications

    The most successful backend engineers I know understand that building great systems is about more than just writing code. It's about creating reliable, secure, and scalable foundations that enable businesses to grow. Master these concepts, practice explaining your reasoning, and remember that every great backend system started with someone asking "How do we make this work at scale?"