← Bytedance Interview Insights

Bytedance·Backend Engineer·Technical Phone Screen·Senior

Senior
Apr 2026

Summary

Backend phone screen at Bytedance that goes pretty deep into Redis and Go internals after a short intro. Not a casual chat, they clearly want specifics and will follow up on anything vague you say.

Questions Asked (9)

Q1

Walk me through the Redis use cases you've implemented and how you chose between them.

System DesignTechnical Trade-offs
Author's notes

They didn't just want a list.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by listing 2-3 concrete Redis use cases you've implemented, then for each, explain the problem, why Redis was chosen over alternatives, and the trade-offs you considered. Conclude by summarizing how you evaluate Redis for different scenarios, emphasizing data structures, performance, and operational factors.

Pro tip: Quantify the impact of each use case (e.g., reduced latency by X%, saved $Y in infrastructure costs) to demonstrate business value. Also, mention a case where you decided *not* to use Redis to show balanced judgment.

1. Set the context

Briefly describe your background and the systems you've worked on, then preview the Redis use cases you'll discuss.

2. Detail each use case

For each use case, explain the problem, why Redis was a good fit (e.g., speed, data structures), and how you implemented it.

3. Explain the decision process

Describe how you compared Redis with alternatives (e.g., Memcached, database caching, Kafka) and the factors you weighed (performance, scalability, cost, complexity).

4. Discuss trade-offs and challenges

Mention any limitations or issues you encountered (e.g., persistence, memory management, clustering) and how you mitigated them.

5. Summarize and reflect

Conclude with key lessons learned and how you now approach choosing Redis for new projects.

Key Points to Mention

  • Caching (e.g., session store, page cache) with TTL and eviction policies
  • Real-time analytics or leaderboards using sorted sets
  • Pub/Sub or Streams for messaging and event processing
  • Rate limiting with counters and expiration
  • Distributed locks with Redlock or simple SETNX
  • Trade-offs: persistence (RDB vs AOF), memory optimization, clustering, and alternatives like Memcached or Kafka

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

What are the differences between RDB and AOF persistence in Redis, and when would you pick one over the other?

System DesignTechnical Trade-offs
Author's notes

Pretty standard if you've worked with Redis seriously.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clearly defining RDB and AOF, then compare them across key dimensions like durability, performance, and recovery. Finally, explain how to choose based on use case, mentioning hybrid persistence and trade-offs.

Pro tip: Mention that in production, many teams use a hybrid approach (RDB + AOF) to balance fast recovery and minimal data loss, and that Redis 4.0+ supports this natively. Also, note that AOF can be configured with different fsync policies to tune durability vs. performance.

1. Define RDB and AOF

Briefly explain that RDB takes point-in-time snapshots of the dataset at specified intervals, while AOF logs every write operation received by the server.

2. Compare key characteristics

Contrast them on durability (AOF more durable, configurable fsync), performance (RDB faster for backups, AOF may impact write throughput), file size (RDB compact, AOF larger), and recovery speed (RDB faster to load).

3. Discuss use cases and trade-offs

Explain when to pick each: RDB for disaster recovery, backups, and faster restarts; AOF for higher durability and minimal data loss. Mention that combining both leverages strengths.

4. Mention advanced configurations

Highlight AOF fsync policies (always, everysec, no) and Redis 4.0+ hybrid persistence (RDB + AOF) for optimal balance.

Key Points to Mention

  • RDB is a snapshot of the dataset at a point in time; AOF logs every write operation.
  • Durability: AOF with fsync always/everysec provides better durability than RDB.
  • Performance: RDB has less impact on write throughput; AOF can slow writes due to fsync.
  • Recovery: RDB loads faster; AOF replay can be slower but more complete.
  • File size: RDB is more compact; AOF can grow large and requires rewrite/compaction.
  • Hybrid persistence (RDB + AOF) in Redis 4.0+ combines fast recovery with minimal data loss.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How do Redis eviction policies work and what problems can they cause?

System DesignRoot Cause Analysis
Author's notes

Went okay.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the core eviction policies (noeviction, allkeys-lru, volatile-lru, etc.) and how Redis selects keys for eviction. Then discuss the problems they can cause, such as data loss, performance degradation, and memory pressure, using concrete examples. Finally, tie it back to system design and root cause analysis by suggesting mitigation strategies.

Pro tip: Mention that eviction is a symptom of insufficient memory planning; the real fix is often better capacity planning, monitoring, and using Redis as a cache with appropriate TTLs rather than as a primary data store.

1. Define eviction policies

List the main policies: noeviction, allkeys-lru, allkeys-lfu, allkeys-random, volatile-lru, volatile-lfu, volatile-random, volatile-ttl. Explain that 'allkeys' applies to all keys, while 'volatile' only applies to keys with an expiration set.

2. Explain eviction mechanics

Describe how Redis samples keys and evicts based on the policy. Mention that LRU/LFU are approximated using sampling, not exact, to save memory and CPU.

3. Identify potential problems

Discuss issues like unexpected data loss (especially with allkeys policies), increased latency due to eviction overhead, memory fragmentation, and the risk of evicting important keys if TTLs are not set properly.

4. Relate to system design and root cause analysis

Explain how eviction can lead to cache misses, increased load on backend databases, and cascading failures. Emphasize the importance of monitoring eviction rates and memory usage.

5. Suggest mitigation strategies

Propose solutions: set appropriate maxmemory and policies, use TTLs, monitor with INFO stats, scale vertically/horizontally, or use Redis Cluster. Highlight that eviction is a symptom, not the root cause.

Key Points to Mention

  • maxmemory configuration and its role in triggering eviction
  • Difference between allkeys-* and volatile-* policies
  • Approximated LRU/LFU algorithms and their trade-offs
  • Impact of eviction on cache hit rate and backend load
  • Monitoring eviction metrics (evicted_keys, keyspace hits/misses)
  • Best practices: use Redis as a cache, set TTLs, avoid noeviction in production unless data is critical

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

What are hot keys and big keys in Redis, and how do you deal with them?

System DesignRoot Cause Analysis
Author's notes

This is where I felt most confident.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clearly defining hot keys and big keys, explaining why they are problematic in a distributed Redis environment. Then, walk through detection methods and mitigation strategies, emphasizing both short-term fixes and long-term architectural solutions. Finally, relate your answer to real-world scenarios, such as handling sudden traffic spikes or large data structures.

Pro tip: Mention that hot keys often require a combination of client-side caching, key splitting, and read replicas, while big keys are best addressed by data modeling changes and gradual migration. Show awareness of trade-offs, like increased complexity versus performance gains.

1. Define hot keys and big keys

Explain that hot keys are keys accessed disproportionately often, causing load imbalance, while big keys are keys with large values (e.g., large hashes, lists, or strings) that can cause latency and memory issues.

2. Explain the impact

Describe how hot keys can overload a single Redis node, leading to CPU spikes, network saturation, and increased latency. Big keys can cause slow operations, memory fragmentation, and blocking during deletion or migration.

3. Detection techniques

Mention tools like Redis's MONITOR command, slow log, and third-party monitoring (e.g., RedisInsight, Prometheus). For big keys, use redis-cli --bigkeys or scan and analyze key sizes.

4. Mitigation strategies for hot keys

Discuss solutions like client-side caching, using read replicas, sharding the hot key by adding a random suffix (key splitting), or using a local cache. Also, consider rate limiting or queueing requests.

5. Mitigation strategies for big keys

Suggest splitting big keys into smaller ones (e.g., sharding a large hash), using compression, or migrating to a different data model. For existing big keys, delete them asynchronously using UNLINK or scan and delete in batches.

Key Points to Mention

  • Hot keys cause uneven load distribution and can lead to single-node bottlenecks.
  • Big keys increase memory usage and can cause latency spikes during operations like DEL or expiration.
  • Detection: use MONITOR, slow log, redis-cli --bigkeys, and custom monitoring.
  • Hot key solutions: key splitting, client-side caching, read replicas, and rate limiting.
  • Big key solutions: data sharding, compression, and asynchronous deletion.
  • Trade-offs: solutions may add complexity or cost, so choose based on access patterns and business needs.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

How does Go's goroutine scheduler work?

Technical Trade-offsSystem Design
Author's notes

Blanked for a second on the M:N threading model terminology.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the GMP model (Goroutines, M's, P's) and how it enables efficient scheduling. Then describe the work-stealing algorithm and how it balances load across processors, highlighting how this design minimizes context switching and maximizes parallelism. Finally, connect it to practical implications like scalability and performance in backend systems.

Pro tip: Mention that the scheduler is cooperative at safe points (function calls, channel operations) and that Go 1.14+ introduced asynchronous preemption to prevent long-running goroutines from blocking others. This shows you're up-to-date with recent improvements.

1. Introduce the GMP model

Define Goroutines (G), OS threads (M), and logical processors (P). Explain that P's are the key to scheduling, as each P has a local run queue of goroutines.

2. Explain the scheduling algorithm

Describe how the scheduler assigns goroutines to P's, and how work-stealing allows idle P's to steal from others' run queues or the global queue.

3. Discuss blocking and preemption

Cover how blocking system calls cause M's to hand off their P to another M, and how goroutines yield at safe points. Mention asynchronous preemption for long-running goroutines.

4. Highlight performance implications

Explain how this design reduces context switching overhead, enables efficient use of multiple cores, and supports massive concurrency (e.g., millions of goroutines).

5. Connect to backend engineering

Relate the scheduler to real-world backend scenarios, such as handling high-throughput requests, and trade-offs like latency vs. throughput.

Key Points to Mention

  • GMP model: Goroutines, OS threads (M), and logical processors (P)
  • Local run queues per P and global run queue
  • Work-stealing algorithm for load balancing
  • Handling of blocking system calls (M handoff)
  • Cooperative and asynchronous preemption (Go 1.14+)
  • Scalability and performance benefits (e.g., millions of goroutines, low context-switching overhead)

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

How does garbage collection work in Go and how can it affect a backend service under load?

Technical Trade-offsSystem Design
Author's notes

Talked about the concurrent tri-color mark-and-sweep, stop-the-world pauses, and how GC pressure shows up as latency spikes.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining Go's concurrent, tri-color mark-and-sweep garbage collector and its low-latency design goals. Then discuss how GC behavior changes under load, focusing on CPU overhead, memory pressure, and latency spikes. Finally, share practical mitigation strategies like tuning GOGC, reducing allocations, and using sync.Pool.

Pro tip: Mention that while Go's GC is designed for low pause times, it can still cause throughput degradation under high load due to increased GC frequency and CPU usage. Show you understand the trade-off between memory and CPU by discussing GOGC tuning and allocation reduction.

1. Explain Go's GC mechanism

Describe the concurrent, tri-color mark-and-sweep algorithm, write barriers, and how it achieves low pause times by running concurrently with the application.

2. Discuss GC behavior under load

Explain how increased allocation rates and heap growth trigger more frequent GC cycles, leading to higher CPU usage and potential latency spikes due to assist and background marking.

3. Identify performance impacts

Cover effects like reduced throughput, increased tail latencies, and memory bloat if GOGC is set too high or too low.

4. Share mitigation strategies

Discuss tuning GOGC, using GOMEMLIMIT, reducing allocations via object reuse (sync.Pool), and profiling with pprof to identify allocation hotspots.

5. Relate to backend service design

Connect GC considerations to system design choices, such as choosing data structures, batching, and concurrency patterns to minimize GC pressure.

Key Points to Mention

  • Go's GC is concurrent and non-generational, using a tri-color mark-and-sweep algorithm with write barriers.
  • Under load, higher allocation rates cause more frequent GC cycles, increasing CPU usage and potentially causing latency spikes.
  • GOGC environment variable controls the heap growth ratio; tuning it can balance memory and CPU trade-offs.
  • GOMEMLIMIT (Go 1.19+) sets a soft memory limit, helping prevent OOM kills in containerized environments.
  • Reducing allocations through sync.Pool, preallocation, and efficient data structures can significantly decrease GC overhead.
  • Profiling with pprof (heap, CPU) is essential to identify allocation hotspots and GC-related bottlenecks.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q7

What are common concurrency bugs in Go and how do you prevent or detect them?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Data races and deadlocks, covered both.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by categorizing common concurrency bugs in Go (e.g., data races, deadlocks, goroutine leaks, channel misuse) and then discuss prevention and detection strategies for each. Emphasize Go-specific tools like the race detector and best practices such as proper synchronization and context usage. Conclude with a real-world example or trade-off to demonstrate practical experience.

Pro tip: Mention that while the race detector is powerful, it only catches races that occur during execution, so combining it with careful code review and design patterns is essential. Also, highlight the importance of understanding the Go memory model to reason about visibility and ordering.

1. Categorize concurrency bugs

List the main types: data races, deadlocks, goroutine leaks, channel misuse (e.g., blocking on unbuffered channels), and improper use of sync primitives. Briefly explain each.

2. Explain prevention techniques

For each bug type, describe preventive measures: using mutexes or atomic operations for shared data, avoiding nested locks, using context for cancellation, and ensuring goroutines have exit conditions.

3. Discuss detection tools

Mention Go's built-in race detector (go test -race), pprof for goroutine profiling, and static analysis tools like go vet. Explain how they help identify issues.

4. Highlight best practices

Emphasize design principles: prefer channels over shared memory, use sync.WaitGroup for coordination, limit goroutine lifetimes, and document concurrency assumptions.

5. Provide a concrete example

Share a personal experience or hypothetical scenario where a concurrency bug was encountered and resolved, demonstrating practical application of the above.

Key Points to Mention

  • Data races and the Go memory model
  • Deadlocks from lock ordering or channel blocking
  • Goroutine leaks due to missing cancellation
  • Channel misuse: closing, nil channels, and select statements
  • Race detector and profiling tools
  • Context package for cancellation and timeouts

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q8

How do you use context for cancellation and timeout propagation in Go?

System DesignAPI & Integrations
Author's notes

Felt like a gimme after the harder questions.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Explain that context.Context is the idiomatic way to propagate cancellation and deadlines across API boundaries and goroutines in Go. Describe how to create contexts with cancellation or timeout, pass them through call chains, and handle cancellation in concurrent operations. Emphasize best practices like checking ctx.Done() and avoiding context leaks.

Pro tip: Mention that you should never store contexts in structs; always pass them explicitly as the first parameter to functions. Also, highlight that context cancellation is cooperative—functions must check ctx.Done() to respond promptly.

1. Define Context Purpose

Explain that context.Context carries deadlines, cancellation signals, and request-scoped values across API boundaries and between goroutines.

2. Create Contexts

Describe how to create root contexts with context.Background() or context.TODO(), and derive cancellable/timeout contexts using context.WithCancel, context.WithTimeout, or context.WithDeadline.

3. Propagate Context

Show how to pass the context as the first argument to functions, especially those making network calls or spawning goroutines, ensuring it flows through the entire call chain.

4. Handle Cancellation

Explain how to listen for cancellation by selecting on ctx.Done() in blocking operations, and how to clean up resources (e.g., cancel functions) to avoid leaks.

5. Apply Timeouts

Illustrate setting timeouts with context.WithTimeout and handling the resulting context.DeadlineExceeded error, ensuring downstream calls respect the deadline.

Key Points to Mention

  • context.Context interface and its role in cancellation and timeout propagation
  • context.WithCancel, context.WithTimeout, and context.WithDeadline for creating derived contexts
  • Passing context as the first parameter to functions and not storing it in structs
  • Checking ctx.Done() channel to detect cancellation and return early
  • Using context in HTTP servers and clients (e.g., http.Request.Context())
  • Avoiding context leaks by always calling cancel functions

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q9

How do you handle errors idiomatically in Go?

Technical Trade-offsAPI & Integrations
Author's notes

Short discussion.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining Go's explicit error handling philosophy, contrasting it with exceptions. Then walk through idiomatic patterns like returning errors, wrapping with context, and using sentinel errors or custom types. Finally, discuss trade-offs and best practices for large-scale systems.

Pro tip: Mention that errors are values in Go, and demonstrate how wrapping errors with %w preserves the chain for errors.Is and errors.As, which is crucial for debugging and API design.

1. Explain Go's error philosophy

Highlight that errors are explicit return values, not exceptions, promoting clear control flow and forcing developers to handle them.

2. Describe basic error handling patterns

Cover returning errors as the last return value, checking immediately, and avoiding panic for recoverable errors.

3. Discuss error wrapping and inspection

Explain wrapping with fmt.Errorf and %w, and using errors.Is and errors.As for sentinel and typed errors.

4. Address custom error types and sentinel errors

Show when to define custom error types for structured data and sentinel errors for specific conditions.

5. Cover trade-offs and best practices

Discuss balancing verbosity with clarity, logging vs returning, and handling errors in concurrent code.

Key Points to Mention

  • Errors are values: return them explicitly, don't panic for normal failures.
  • Wrap errors with context using fmt.Errorf("...: %w", err) to preserve the chain.
  • Use errors.Is for sentinel errors and errors.As for typed errors.
  • Define custom error types when you need to carry structured data.
  • Avoid logging and returning the same error; decide on one responsibility.
  • In concurrent code, use channels or errgroup to propagate errors safely.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.