These preparation themes come from the questions in this role’s bank. They help you organise your examples; individual employers may assess different things.
Code quality & collaboration
Computer science fundamentals
Collaboration
Incident
Java
PHP
A useful preparation sequence
Choose your experience level and the round you expect.
Answer one question in your own words before opening its guide.
Compare your reasoning, evidence and trade-offs; adapt the answer to your experience.
Practise the follow-up, then revisit one answer you want to improve.
Representative questions and answer guidance
Open any question to read its answer. The complete guidance is included on this page.
Behavioural · Mid-level / Senior
1. How do you approach reviewing someone else's code?
Answer guide
Read the description first to understand the intent, then check correctness, tests, readability and any risk to security or performance. Focus on the important issues and mark style points as optional. Phrase comments as questions or suggestions and explain the reason, and say what is good, not only what needs changing. For large changes, ask for smaller pull requests, and respond quickly so the author is not blocked.
2. What is the difference between a process and a thread?
Answer guide
A process is a running program with its own memory space and resources. A thread is a unit of execution inside a process, and the threads of one process share its memory. Threads are lighter to create and switch between, and they communicate easily through shared data, which is also why they need care with locks and race conditions. Processes are more isolated, so a crash in one does not normally bring down another.
What this question explores
Core operating system understanding.
Common mistakes
Saying they are the same thing
Ignoring shared memory and its risks
Practise a follow-up
What is a race condition and how do you prevent one?
When would you use multiple processes instead of threads?
3. How do you handle a design disagreement with a senior engineer?
Answer guide
Treat it as a chance to learn, not a contest. First make sure I understand their view and ask about their reasons. Then agree on the requirements and what matters most, such as speed, cost or ease of change. Bring evidence, like a small prototype, benchmark or examples, and compare the tradeoffs of each approach politely. If we still differ, ask the team lead to decide. Write down the decision and reasoning, and support it fully, even if it is not mine.
Key points
Compare requirements, evidence, tradeoffs and decision record.
4. A deployment doubles error rates but only for one region. What do you do first?
Answer guide
First find out how bad it is. Check how many users in that region are affected and what errors they see. If the impact is serious, stabilise quickly by rolling back the deployment or shifting traffic away, rather than hunting for the cause while users suffer. Then look at telemetry for that region, comparing config, dependencies, data and traffic with healthy regions. Tell the team and stakeholders what you know, and keep updating them. Afterwards, write a review and add checks to catch regional differences earlier.
Key points
Triage impact, stabilize or rollback, inspect telemetry and communicate.
The == operator asks whether two variables point to the very same object in memory, while equals asks whether two objects should count as equal in value, but only if the class overrides it; the default version just behaves like ==. Whenever you override equals you must also override hashCode consistently, otherwise a HashMap or HashSet may fail to find a key that looks equal. Primitives such as int are always compared with ==. In review, I would use equals for object values and keep == for primitives, enum constants and deliberate identity checks.
What this question explores
Whether you can separate reference identity from logical equality and know the hashCode contract that goes with it.
Common mistakes
Saying == compares values for all objects, then being surprised when two equal strings differ.
Overriding equals but forgetting hashCode, so hash-based collections lose entries.
Practise a follow-up
What exactly goes wrong in a HashSet if two equal objects return different hash codes?
Why can == on small Integer objects sometimes give true and sometimes false?
6. How would you prevent SQL injection in a PHP application?
Answer guide
Use prepared statements with bound parameters, through PDO or mysqli, so user input is sent as data and never becomes part of the SQL text. Escaping strings by hand is fragile and should not be the main defence. Parameters cannot bind identifiers such as column names or sort direction, so for those you check the value against a fixed allowlist in code. In practice I review every query for concatenation, use a static analysis tool to catch it, and keep a few injection-style inputs in the regression suite.
What this question explores
Layered defence against SQL injection, including the cases prepared statements do not cover.
Common mistakes
Relying on manual escaping or input filtering instead of parameterised queries.
Binding values safely but concatenating a user-supplied column name or ORDER BY direction.
Practise a follow-up
How do you safely build a dynamic ORDER BY clause with a prepared statement?
Why does least-privilege for the database user matter even with parameterised queries?
Clarify the requirements first: expected traffic, link lifetime, custom aliases and analytics. The core is a write path that creates a short key and a much heavier read path that redirects. Generate keys with a counter encoded in base 62, or with random keys checked for collisions, and store the key-to-URL mapping in a key-value or relational store. Put a cache in front of reads, choose a permanent or temporary redirect depending on whether you need click analytics, and add rate limiting and expiry. Then discuss scaling: partitioning the store and making key generation work across many servers.
What this question explores
Structured system design: requirements, data model, trade-offs and scaling.
Common mistakes
Jumping to technology before clarifying requirements
Ignoring that reads far outnumber writes
Not discussing key collisions
Practise a follow-up
How would you handle a link that suddenly goes viral?
8. How do you decide between refactoring and rewriting a system?
Answer guide
Start with the business problem: what is the current system costing in delays, defects or risk, and what would a change unlock? Default to incremental refactoring, guarded by tests, because it delivers value continuously and keeps the system running. A rewrite is justified only when the technology or architecture blocks essential goals and the knowledge to replicate the existing behaviour is available. If a rewrite is needed, prefer replacing the system piece by piece so that both versions can run side by side.
What this question explores
Pragmatism and risk awareness, not a preference for new technology.
Common mistakes
Wanting to rewrite because the code is unpleasant to read
Ignoring hidden behaviour that the old system provides
Practise a follow-up
How would you make the case to a non-technical sponsor?
9. What is a goroutine and how should it be stopped when its request is canceled?
Answer guide
A goroutine is a function running concurrently, scheduled by the Go runtime and much lighter than an operating system thread. It does not stop by itself when a request is canceled, so you pass it a context and have it watch ctx.Done in a select alongside its blocking work, such as a channel receive or a send. When the context is canceled, the goroutine returns and its deferred cleanup runs. Every goroutine you start should have a clear owner and a known way to exit, and a small leak-focused test that counts goroutines after cancellation is a good habit.
What this question explores
Whether you understand that goroutines need explicit shutdown and can use context cancellation to avoid leaks.
Common mistakes
Believing a goroutine is stopped automatically when the function that launched it returns.
Using only time.Sleep or a shared boolean instead of a context or channel to signal shutdown.
Practise a follow-up
How does a goroutine leak show up in production, and how would you find it?
What is the difference between context.WithCancel and context.WithTimeout?
10. Why is a mutable default argument risky in Python?
Answer guide
Python evaluates default argument expressions once, when the def statement runs, not on every call. So a default like an empty list becomes one shared object, and appending to it in one call changes what the next call sees. A small example is a function that adds an item to a default list and returns it; calling it twice gives a list with both items. The usual fix is to default to None and create a fresh list inside the body when None is received. Immutable defaults such as numbers, strings and tuples are safe. Reviewers often catch this with a linter rule, and a two-call unit test shows the bug clearly.
What this question explores
Whether you know when Python evaluates defaults and can spot shared-state bugs early.
Common mistakes
Thinking a new default list is created on every call, so the bug is unexpected.
Fixing it by copying the list after use instead of using a None sentinel.
Practise a follow-up
Is a default tuple or string argument safe, and why?
How can a mutable default ever be useful on purpose, for example for caching?
11. How do let, const and var differ in scope and reassignment?
Answer guide
Both let and const are block-scoped, meaning they exist only inside the braces where they are declared, while var is function-scoped and leaks out of blocks like if and for. Variables declared with var are hoisted and start as undefined; let and const are hoisted too but sit in a temporal dead zone until their line runs, so early use throws an error. let can be reassigned; const cannot be rebound, yet an object held by const can still have its properties changed. In new code I default to const, use let when reassignment is needed, and avoid var. A quick loop with closures shows the difference well.
What this question explores
Clear fundamentals of scope, hoisting and reassignment, including the const-is-not-immutable misconception.
Common mistakes
Saying const makes an object or array immutable rather than only preventing reassignment.
Claiming let and const are not hoisted at all and ignoring the temporal dead zone.
Practise a follow-up
What does a loop that creates setTimeout callbacks print with var compared with let?
How would you make an object truly immutable, and what are the limits of that?
12. Do TypeScript types validate data received over an API at runtime?
Answer guide
No. TypeScript types exist only at compile time and are erased from the JavaScript that runs, so nothing checks the shape of a JSON response as it arrives. If a server returns a different field or a null, a type annotation like User will not stop your code from treating it as valid. Treat all external data as unknown, then validate it at the boundary with a runtime schema library or hand-written guards, and only after that use the safe type. The compiler still helps for internal code. A useful approach is to derive the static type from the schema so the two never drift apart.
What this question explores
Whether you know the limit of static typing at system boundaries and how to validate untrusted data at runtime.
Common mistakes
Assuming that annotating a fetch result with an interface guarantees the data matches it.
Using a type assertion with as to silence the compiler instead of validating the payload.
Practise a follow-up
What is the difference between typing a value as any and as unknown?
How would you keep a runtime schema and a TypeScript type from drifting apart?
Choose one answer containing an example or practical sequence. Explain what you would actually do, what you would check and when you would ask for help. Keep claims about your experience honest.
For technical or regulated work, check current documentation and applicable local requirements alongside this practice material.