cswork / libraryOpen practice workspace

Interview guides · Bravotech

Bravotech Software Engineer Interview Guide

Bravotech Software Engineer interview guide: four reported rounds, coding, system design and behavioral questions, and a 7-day prep plan.

The 60-second brief

Candidate-facing descriptions of Bravotech do not name a specific product line; they speak of various products and services. What they do say about the Software Engineer role is concrete enough to prepare from: the work involves systems of real scale and complexity, including real-time systems used by customers in many countries, and it sits alongside product management, quality assurance and user experience colleagues. The problem areas listed are data management, cloud computing and software architecture, so expect questions about how you build, store, deploy and evolve software, not only how you write a function.

This guide is for anyone preparing for the Bravotech Software Engineer interview loop. It covers the four reported rounds, the five groups of questions candidates report (technical fundamentals, system design, behavioral, problem-solving and debugging, and coding), the languages and tools the role lists (Java, C# or Python; React or Angular; AWS or Azure; Git and Jenkins), and a seven-day plan. Behavioral questions get full answer structures; the technical questions are tied into the rounds and the plan.

Candidates report four rounds spread over roughly three to five weeks: Initial Screening, Technical Assessment, Interviews with Senior Engineers and Cross-Functional Interviews. The final stage is described as potential conversations with stakeholders from other departments.

Focus areas

  • Software Engineering (General)
  • Programming Fundamentals
  • Testing Strategies

Overview

The role, as candidates describe it, mixes writing and reviewing code, debugging and testing, turning requirements from product managers and designers into technical specifications, and joining architecture discussions. The listed requirements are proficiency in Java, C# or Python, experience with web frameworks such as React or Angular, a solid grasp of algorithms and data structures, and familiarity with a cloud platform such as AWS or Azure. Docker, Kubernetes, CI/CD pipelines and some exposure to data analysis or machine learning tools are listed as extras. Git and Jenkins appear as example tools.

The reported questions are broad fundamentals rather than puzzles: object-oriented programming, synchronous versus asynchronous code, optimizing a slow algorithm, code quality, designing a scalable web application, choosing data storage, microservices, API design, debugging production, troubleshooting a failing deployment, linked lists, a sliding-window string problem, sorting, dynamic programming and testing. Because the questions are open-ended, the answer that stands out is the one with a concrete example from your own language and project, a stated trade-off, and an edge case you checked.

Candidate accounts also list four evaluation areas: role-related knowledge, problem-solving ability, leadership and culture fit. Leadership here is framed as influence and communication, so a story about persuading a team or explaining a trade-off to a non-engineer carries as much weight as one about shipping code. Culture fit is best prepared as collaboration stories with real detail, such as a conflict you resolved or feedback you acted on.

A practical way to prepare: for each concept question, write a one-sentence definition, a short example in your strongest language, and one trade-off. For each coding question, write the solution, its complexity and three edge-case tests. For each behavioral question, write a story with your own actions and a measurable result. The seven-day plan below sequences that work.

The Bravotech interview process

The four stages below are what candidates describe, not a published process. Use them to decide where your practice time goes.

Initial Screening

Candidates describe the Initial Screening as a review of your resume and professional background to judge fit. Treat it as the round where your story has to be coherent: why your projects lead to this role, and which of the listed technologies (Java, C# or Python, web frameworks, a cloud platform) you have used for real. Candidate accounts also say you should be ready to discuss your technical projects and the technologies in them in depth, so expect to be asked about decisions, not just job titles.

What to demonstrate

  • How clearly you walk through your resume and professional background
  • How well your experience lines up with the reported requirements: a language such as Java, C# or Python, web technologies, cloud
  • Whether you can talk about your own projects and tools in depth, including version control practice

How to prepare

  • Pick two or three projects and write for each the problem, your specific contribution, the stack and one decision you would defend; keep Java, C# or Python usage explicit where it is true
  • Prepare your answer to the version control question: branching approach, how you handle merge conflicts, and one time history or bisecting helped you
  • Have a short account of why you are moving and why this role, plus your logistics, ready before the call

Technical Assessment

The Technical Assessment is described as a demonstration of coding and system design skills through practical exercises. Candidates do not report a fixed format here, so prepare for both halves: writing working code in your chosen language with tests, and sketching a design while naming the trade-offs. The coding and algorithm questions and the system design questions reported for Bravotech are the practice material for this stage.

What to demonstrate

  • Working code for algorithm and data-structure problems, with correct complexity analysis
  • System design reasoning: components, storage choices, scaling and trade-offs
  • How you test and verify what you wrote

How to prepare

  • Solve the reported coding questions (reverse a linked list, longest substring without repeating characters, a basic sort, a dynamic programming problem) in one language, each with complexity and edge-case tests
  • Practise the design questions out loud with a diagram: stateless application tier, load balancer, cache, database, queue, and what fails first at higher load
  • Prepare a short answer on optimizing a slow algorithm: measure first, then change the algorithm or data structure, then re-measure

Interviews with Senior Engineers

Candidates describe Interviews with Senior Engineers as an engagement to evaluate technical expertise and problem-solving. Reports do not specify a format, so prepare for depth conversations on your own projects and for open problem-solving: debugging a production issue, troubleshooting a failing deployment, and weighing trade-offs between solutions. Practice thinking aloud in a fixed sequence so you do not jump to a theory.

What to demonstrate

  • Depth of technical knowledge in the languages and tools you claim
  • Problem-solving approach on open-ended or debugging-style questions
  • How you reason about trade-offs, such as monolith versus microservices or storage options

How to prepare

  • Write a debugging sequence you can recite: what changed, how to reproduce, logs and metrics, bisect the suspects, confirm the fix, prevent recurrence
  • Prepare a failing-deployment checklist tied to a pipeline: build result, configuration and secrets, image or artifact version, health checks, rollback
  • Rehearse the system you designed yourself, including the hardest challenge and what you would change; practise the microservices and data storage questions as trade-off discussions

Cross-Functional Interviews

Cross-Functional Interviews are described as potential discussions with stakeholders from other departments to assess collaboration skills. Candidate accounts name product management, quality assurance and user experience as the teams engineers work with, so prepare to talk to people who do not share your vocabulary. This is the stage to have your conflict, prioritization and communication stories fully rehearsed.

What to demonstrate

  • Collaboration with colleagues outside engineering
  • Clarity when explaining technical information to non-technical stakeholders
  • Judgement in prioritizing competing requests and handling disagreement

How to prepare

  • Write STAR stories for conflict within a team, prioritizing under multiple deadlines, and communicating a technical issue to a non-technical audience
  • Practise explaining one architectural decision (for example microservices versus a monolith) in two plain-language sentences with its cost
  • Prepare one example each of working with product management, QA and a designer, naming what each needed from you

Where candidates lose points

Answering the object-oriented or asynchronous programming questions with a textbook list of pillars and no example

For each concept, write a short example in your own language: a class hierarchy where polymorphism removed a conditional, or a blocking call versus an async call with what the thread does while it waits. Then state one cost, such as inheritance coupling or the added complexity of async error handling.

Jumping to a rewrite when asked to optimize a slow algorithm, without measuring or stating complexity

Say you would measure first, find the hot path, state current and target complexity, and then change the data structure or algorithm. Rehearse it on the sorting and substring questions: brute force, the improvement, and why it is faster.

Naming components for the scalable web application design (load balancer, cache, database) with no reasoning about load, state or failure

Fix the scope and the read-versus-write split first. Make the application tier stateless, say what you cache and how it is invalidated, how the database scales, and what happens when one dependency is down. Give one monolith-versus-microservices trade-off with its operational cost.

Coding answers that stop at a passing happy path: a linked-list reversal that loses the next pointer, or a substring window that never moves its left edge correctly

Write the solution, then test an empty input, a single element and a repeated-character case out loud. State time and space complexity. Prepare the dynamic programming question by writing the recurrence and base cases before any code.

Behavioral stories told with plural pronouns, no personal decision and no result

For every STAR story, write down your own three actions and one measurable outcome. If you cannot say what you decided, choose a different story. Rehearse conflict, prioritization, communication and feedback stories until each has a result.

Questions & practice

What are the differences between synchronous and asynchronous programming?

Medium · Technical / Domain Questions

Approach

  1. Define both precisely: a synchronous call blocks the caller until the result is ready; an asynchronous call starts the work and returns at once, with the result delivered later through a callback, promise, future or await.
  2. Separate concurrency from parallelism: an event loop such as Node.js or Python asyncio interleaves many waiting I/O operations on one thread, which helps I/O-bound work and does nothing for CPU-bound work.
  3. Name the runtime mechanics in the stack listed for this role: C# async/await over Task, Java CompletableFuture or a thread pool, JavaScript promises, Python coroutines; await suspends the function without blocking the thread.
  4. Cover the pitfalls: a blocking call such as time.sleep or a synchronous DB driver inside an async handler stalls every request on that loop; blocking on .Result or .Wait() in C# can deadlock under a synchronization context; unhandled promise rejections lose errors.
  5. Give the trade-off: async raises throughput for many slow I/O calls, but makes control flow, stack traces and error handling harder, so it is not worth it for simple CPU-bound or low-traffic code.

Follow-up

  • What happens if a CPU-heavy function runs inside a Node.js request handler, and how would you move it off the event loop?
  • How would you cap 10,000 outbound HTTP calls at 50 in flight at a time?
  • How do errors propagate differently in callback code and in async/await code?

Describe how you would optimize a slow-running algorithm.

Medium · Technical / Domain Questions

Approach

  1. Measure before changing anything: reproduce with realistic input sizes and run a profiler (cProfile, Java Flight Recorder or async-profiler, dotnet-trace) to find where the time actually goes, and confirm whether it is CPU, I/O or memory.
  2. Attack the complexity first: replace a nested-loop membership check (O(n*m)) with a hash set (O(n+m)), sort once and use binary search or two pointers, add prefix sums so each range query is O(1) after O(n) setup, or memoise repeated subproblems.
  3. Then constant factors: build strings with StringBuilder or join instead of repeated concatenation in a loop (quadratic in Java), avoid allocations in the hot loop, batch I/O, and remove N+1 database queries.
  4. State the trade-off of each change: a hash set or cache spends memory to save time, and precomputation only pays off when there are many queries.
  5. Verify: keep correctness tests passing, benchmark before and after on the same input, and add a performance check so the regression cannot quietly return.

Follow-up

  • The profile shows most of the time is waiting on the network, not computing. What do you change instead?
  • The hash set no longer fits in memory. What are your options?
  • How would you stop this slowdown from coming back after the next release?

Write a function to reverse a linked list.

Medium · Coding / Algorithms

Approach

  1. Use three pointers iteratively: prev = null, curr = head; in the loop save next = curr.next, set curr.next = prev, then advance prev = curr and curr = next; return prev as the new head.
  2. State the complexity: O(n) time and O(1) extra space, with each node visited once and links rewired in place.
  3. Mention the recursive version (reverse the rest, then head.next.next = head and head.next = null): it is also O(n) time but uses O(n) call stack, which can overflow on long lists (Python's default recursion limit is 1000).
  4. Check edge cases aloud: an empty list, a single node, two nodes, and that the old head's next ends up null so no cycle is left.
  5. Test by building a list from an array, reversing it, and walking it back into an array to compare.

Follow-up

  • Reverse only the nodes between positions m and n.
  • Reverse the list in groups of k nodes.
  • How does the solution change for a doubly linked list?

How would you find the longest substring without repeating characters?

Medium · Coding / Algorithms

Approach

  1. Start from brute force (check every substring, O(n^3), or O(n^2) with a set) and move to a sliding window with left and right pointers.
  2. Keep a map from character to its last seen index; for each right, if the character was seen at an index >= left, move left to that index + 1; then record the index and update best = max(best, right - left + 1).
  3. Explain why the index >= left check matters: on "abba", the final 'a' was last seen before the window, and without the check left would jump backward and give a wrong window.
  4. State the complexity: O(n) time, since each pointer only moves forward, and O(min(n, alphabet size)) space; a 128-entry array replaces the map for ASCII input.
  5. Cover edge cases: an empty string returns 0, all identical characters return 1, and spaces and digits count as characters.

Follow-up

  • Return the substring itself, not just its length.
  • Find the longest substring with at most k distinct characters.
  • How would you handle a stream of characters too large to hold in memory?

Implement a basic sorting algorithm and explain its time complexity.

Medium · Coding / Algorithms

Approach

  1. Pick one algorithm and write it cleanly. Merge sort: split, sort each half recursively, merge with two pointers; O(n log n) in every case, O(n) extra space, and stable if the merge takes from the left half on ties.
  2. Contrast quicksort: O(n log n) on average but O(n^2) in the worst case (for example, sorted input with the first element as pivot), O(log n) average stack, in place and not stable; a random or median-of-three pivot makes the worst case unlikely.
  3. Know when the simple ones win: insertion sort is O(n^2) in the worst case but O(n) on nearly sorted input, stable and in place, which is why hybrids use it for small subarrays.
  4. Connect to real libraries: Python's sorted uses Timsort (stable); Java's Arrays.sort uses dual-pivot quicksort for primitives and TimSort for objects; C# Array.Sort is an unstable introsort. Comparison sorts cannot beat O(n log n), but counting or radix sort reach O(n + k) on bounded integer keys.
  5. Test on an empty array, one element, duplicates, already sorted and reverse-sorted input.

Follow-up

  • How would you sort a file far larger than memory?
  • When does stability matter? Give a multi-key sorting example.
  • Why is quicksort often faster than merge sort in practice despite its worse worst case?

Solve a problem using dynamic programming techniques.

Medium · Coding / Algorithms

Approach

  1. Justify dynamic programming before using it: overlapping subproblems (a naive recursion recomputes the same states) and optimal substructure (the best answer is built from best answers to smaller states).
  2. Define the state in words, then the recurrence, base cases and evaluation order. For minimum coins: dp[0] = 0, dp[a] = min(dp[a - c] + 1) over coins c <= a, with unreachable amounts kept at infinity and returned as -1.
  3. Give the complexity: O(amount x number of coins) time and O(amount) space; for a two-dimensional table such as longest common subsequence it is O(m x n), reducible to one row when each row depends only on the previous one.
  4. Choose between top-down memoisation (easy to write from the recursion, but uses call stack) and bottom-up tabulation (no recursion, and the order is explicit).
  5. Show why greedy fails where needed: with coins {1, 3, 4} and amount 6, greedy takes 4+1+1 (three coins) while the optimum is 3+3 (two).

Follow-up

  • Reconstruct which coins make up the optimal answer, not just the count.
  • Count the number of ways to make the amount instead. Why does loop order decide whether you count combinations or permutations?
  • How would you cut the memory of your table?

Discuss how you would test your code effectively.

Medium · Coding / Algorithms

Approach

  1. In a coding round, list cases aloud before running anything: a normal case, boundaries (empty input, one element, maximum size), duplicates, negative or zero values, invalid input and overflow; then trace one case through the code by hand.
  2. Use systematic techniques: equivalence partitioning and boundary-value analysis to choose cases, and a brute-force reference implementation to check the optimised one on random inputs.
  3. Describe the test layers in a codebase: many fast unit tests, fewer integration tests against a real database or service, and a few end-to-end tests; name frameworks for the role's stack, such as JUnit, xUnit or NUnit, pytest and Jest.
  4. Isolate what is nondeterministic or external: inject the clock and random seed, prefer fakes over deep mocks, and use property-based testing (Hypothesis, jqwik) for invariants such as 'sorting preserves the elements'.
  5. Keep the suite trustworthy: run it on every pull request in CI, fix or quarantine flaky tests quickly, and add a regression test for every production bug.

Follow-up

  • How would you test code that depends on the current time or on randomness?
  • A test fails once in every twenty CI runs. What do you do?
  • What would you deliberately not unit test, and why?

Hold a per-tenant active cap against concurrent creates

Hard · write skew · isolation levels · constraints

A tenant on the standard plan may hold at most 50 resources with status='active'. The create handler runs SELECT count(*) FROM resource WHERE tenant_id = $1 AND status = 'active', compares to 50, then inserts. Two creates arrive 3 ms apart on different instances and the tenant lands at 51. Name the anomaly, say whether PostgreSQL 16 READ COMMITTED or REPEATABLE READ prevents it and why, then give an implementation that holds the cap at READ COMMITTED with the exact statements. Finally, say what changes when the cap is 'at most one running export per tenant' on job_run.

Approach

  1. Name it: write skew. The two transactions read an overlapping set and write disjoint rows, so there is no row-level conflict for the engine to detect and each commit is individually legal.
  2. Rule out the levels precisely. READ COMMITTED takes a fresh snapshot per statement and takes no lock on the counted rows, so both see 49. PostgreSQL's REPEATABLE READ is snapshot isolation: it removes non-repeatable reads and phantoms within the snapshot but still admits write skew, because the anomaly is not a re-read of a changed row, it is a read of a set that a concurrent transaction invalidates. Only SERIALIZABLE closes it, by tracking the read dependency and aborting one transaction with SQLSTATE 40001 — a guarantee that exists only if the application re-runs the whole transaction from the read.
  3. Convert the set predicate into a single-row conflict: keep tenant.active_resource_count and run UPDATE tenant SET active_resource_count = active_resource_count + 1 WHERE tenant_id = $1 AND active_resource_count < 50 in the same transaction as the INSERT. Zero affected rows is the cap, returned as 409. The row lock serialises the decision at any isolation level, and contention is bounded to one tenant's row — which is also the fair-scheduling unit, unlike a global counter that would convoy every tenant behind one row.
  4. State the cost you just took on: a counter is a second source of truth that can drift, so every path that changes status must adjust it inside the same transaction, and a periodic reconciliation has to exist, with resource_revision as the authority for what the count should have been.

Follow-up

  • A resource moves from archived back to active. Which statements change, and what breaks if the counter update and the status change land in different transactions?
  • The cap becomes plan-dependent and a plan can change mid-month. Where does the number 50 live, and who reads it?

Denormalise tenant onto revisions and backfill it live

Hard · denormalisation · online migration · backfill

resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.

Approach

  1. Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
  2. Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
  3. Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
  4. Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.

Follow-up

  • The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
  • How do you verify the backfill actually finished, given rows are still being inserted while it runs?

Explain the concept of object-oriented programming and its benefits.

Medium · Technical / Domain Questions

Approach

  1. Name the four pillars, each with a one-line meaning: encapsulation (state is changed only through methods), abstraction (callers depend on what an object does, not how), inheritance (a subtype reuses and extends a base type) and polymorphism (one call site, behaviour chosen by the runtime type).
  2. Ground it in one small example, such as a PaymentMethod interface with Card and BankTransfer implementations: checkout code calls pay() and never branches on the concrete type, so adding a new method touches no existing caller.
  3. Tie the benefits to maintenance: changes stay local behind an interface, a fake implementation can be injected in unit tests, and duplicated logic shrinks.
  4. Know the language details for Java, C# or Python: Java instance methods dispatch dynamically by default, C# needs virtual and override, and Python has no enforced private members (only the underscore convention and double-underscore name mangling).
  5. Give the cost: deep inheritance trees couple subclasses to base-class internals (the fragile base class problem), so prefer composition, keep hierarchies shallow, and respect Liskov substitution.

Follow-up

  • When would you choose composition over inheritance, and can you show a case where inheritance broke a subclass?
  • What is the difference between an interface and an abstract class in Java or C#?
  • How does an object-oriented design compare with a functional one for code that manages a lot of shared state?

How do you ensure code quality and maintainability?

Medium · Technical / Domain Questions

Approach

  1. Automate the baseline so review time goes to design: a formatter and linter (ruff or Pylint, ESLint, Checkstyle), static analysis, and unit tests that run on every pull request in CI (Jenkins is one of the tools candidates list for this role).
  2. Keep code reviews effective: small pull requests with a single purpose and a description of why, reviewers checking design, naming, error handling and tests rather than style the linter already enforces.
  3. Design for change: single responsibility per module, dependencies injected so they can be faked in tests, clear names, and no abstraction until a second real use case exists.
  4. Treat coverage as a signal, not a target: test behaviour and boundaries, and track outcomes such as escaped defects, change failure rate and how long a typical change takes.
  5. Manage debt explicitly: record it, attach a cost, and pay it down alongside feature work instead of in a rewrite.

Follow-up

  • How would you start improving a legacy module that has no tests at all?
  • A reviewer and you disagree about a design in a pull request. How do you settle it?
  • What coverage number would you set for a team, if any, and why?

How would you design a scalable web application?

Medium · System Design / Architecture

Approach

  1. Pin requirements first: expected users and requests per second, read-to-write ratio, latency target, data size and availability goal; do a quick estimate so every later choice has a number behind it.
  2. Lay out the request path: DNS and a CDN for static assets, a load balancer, stateless application servers scaled horizontally (sessions in Redis or in signed tokens), and a primary database.
  3. Scale reads with a cache (cache-aside with TTLs and explicit invalidation) and read replicas; note that replica lag breaks read-your-writes unless recent writers read from the primary.
  4. Move slow work off the request path through a queue and workers (emails, image processing, reports), and shard the database by a chosen key only when one primary can no longer absorb the writes.
  5. Close with reliability and operations: health checks, autoscaling, instances spread across availability zones, rate limiting, metrics and tracing, and zero-downtime deploys.

Follow-up

  • Traffic grows tenfold. Which component fails first, and how would you know?
  • How do you prevent a cache stampede when a hot key expires?
  • A user updates a profile and immediately sees the old value. Why, and how do you fix it?

What considerations would you take into account for data storage solutions?

Medium · System Design / Architecture

Approach

  1. Start from access patterns: point lookups by key, range scans, joins, aggregations or full-text search; the dominant query decides the store more than the data does.
  2. Map patterns to options: a relational database (PostgreSQL, SQL Server) for transactions and joins, a key-value store (Redis, DynamoDB) for fast lookups by key, a document store for flexible nested records, object storage (S3, Azure Blob) for files, a search index for text and a warehouse for analytics.
  3. State the consistency need: ACID transactions where money or inventory moves, eventual consistency where stale reads are acceptable, and what that choice costs in availability and latency.
  4. Plan for growth and operations: indexes speed reads but slow writes and use storage, replication for reads and failover, partitioning by a key that spreads load evenly, backups with stated recovery point and recovery time objectives.
  5. Add security and cost: encryption at rest and in transit, access control, retention and deletion rules, and the managed-service versus self-hosted trade-off on AWS or Azure.

Follow-up

  • When would you denormalise a relational schema, and what do you give up?
  • How would you change a column type on a large table without downtime?
  • How do you choose a partition key, and what happens with a hot key?

Explain the principles of microservices architecture.

Medium · System Design / Architecture

Approach

  1. Give the core principles: each service owns one business capability and its own data (no shared database), is deployed independently, and talks to others only through APIs (REST, gRPC) or events.
  2. Design for failure because calls cross a network: timeouts on every call, retries with exponential backoff and jitter only for idempotent operations, circuit breakers, and bulkheads so one slow dependency cannot exhaust every thread.
  3. Handle data that spans services without distributed transactions: the saga pattern with compensating actions, the transactional outbox to publish events reliably, and accepting eventual consistency between services.
  4. Name what the approach requires: distributed tracing with correlation IDs, centralised logs, CI/CD per service, and containers and orchestration such as Docker and Kubernetes (listed as nice-to-have for this role).
  5. Give the trade-off against a monolith: independent scaling and deploys versus network latency, harder debugging and operational overhead; a modular monolith is often the better start, split later with the strangler fig pattern.

Follow-up

  • An order service and a payment service must stay consistent. How do you handle a payment failure after the order is created?
  • How would you split an existing monolith without a big-bang rewrite?
  • When would you advise a team against microservices?

Describe a system you designed and the challenges you faced.

Medium · System Design / Architecture

Approach

  1. Pick a system where you made the main design calls, and open with the problem and its numbers: users, traffic, data volume, latency or uptime target, and the constraints on time and team.
  2. Sketch the architecture in components and data flow, then go deep on one or two decisions: the alternatives you considered, why you chose one, and what it cost.
  3. Describe the hardest challenge concretely (a scaling bottleneck, a consistency bug, a migration) and how you diagnosed it: the metric, log or test that showed the cause.
  4. Give the outcome with evidence (latency, error rate, cost, delivery date) and say clearly which parts were yours, in the first person.
  5. End with what you would change now; a candid reversal of one decision shows you can judge a design after the fact.

Follow-up

  • What in that system would break first at ten times the load?
  • Which decision would you reverse with what you know now?
  • How did you validate the design before building all of it?

How do you approach API design?

Medium · System Design / Architecture

Approach

  1. Start from the consumers and their use cases, then model resources: nouns in paths, HTTP methods with their meaning, and accurate status codes (201 Created, 400, 404, 409 Conflict, 429 Too Many Requests).
  2. Make retries safe: GET, PUT and DELETE are idempotent by definition and POST is not, so accept an idempotency key on POST and return the stored result when the same key arrives again.
  3. Choose pagination deliberately: cursor-based pagination stays correct under concurrent inserts and stays fast deep into a list, while offset pagination can skip or repeat rows and slows down at large offsets.
  4. Plan evolution: additive changes are backward compatible, breaking changes go to a new version (path or header), and old versions get a deprecation period; keep one consistent error body with a machine-readable code.
  5. Cover the cross-cutting parts: authentication (OAuth 2.0 or tokens), authorisation per resource, rate limits, input validation, and an OpenAPI specification as the contract.

Follow-up

  • A client's POST times out and it retries. How does your API avoid creating the record twice?
  • How would you roll out a breaking change to an API with external consumers?
  • When would you choose gRPC or GraphQL over REST?

Present a technical problem and walk us through your thought process to solve it.

Medium · Problem-Solving / Case Studies

Approach

  1. Choose a problem with real technical substance and state it in two or three sentences: the system, the symptom or goal, and the constraints such as data size, latency or deadline.
  2. Show how you clarified it: the questions you asked, what you measured, and which assumptions you wrote down before designing anything.
  3. Lay out two or three options with their trade-offs in complexity, cost and risk, then explain the choice and the key implementation details.
  4. Explain how you verified it: tests, a benchmark or a staged rollout, and the measured result.
  5. If the problem is given to you live instead, follow the same sequence aloud: clarify the inputs, work a small example, state a brute-force solution and its complexity, improve it, then test edge cases.

Follow-up

  • Which alternative did you reject, and what would have made it the right choice?
  • If the main constraint changed, for example ten times the data, what would you redo?
  • How did you know the solution worked rather than just passing the tests you wrote?

How do you assess the trade-offs in any given solution?

Medium · Problem-Solving / Case Studies

Approach

  1. Name the criteria and rank them for the situation: correctness, latency, cost, delivery time, maintainability and operational risk; the ranking is what makes a trade-off decidable.
  2. Put two or three real options side by side and estimate each against the criteria with numbers where possible (milliseconds, dollars per month, engineer-weeks).
  3. Weigh reversibility: a choice that is easy to undo can be made quickly, while a data model or public API needs more evidence first.
  4. Use a concrete example, such as a cache versus a read replica: the cache is faster but adds invalidation and staleness, while the replica keeps SQL semantics but adds lag and cost.
  5. Decide, state what you are giving up, and name the signal that would make you revisit the choice.

Follow-up

  • How do you decide when you lack the data to compare the options?
  • Tell me about a trade-off you got wrong and how you found out.
  • How do you handle a stakeholder who weighs the criteria differently from you?

How would you approach debugging a complex issue in production?

Medium · Problem-Solving / Case Studies

Approach

  1. Stabilise first: assess user impact and mitigate (roll back, disable a feature flag, add capacity) before hunting for the root cause.
  2. Scope the problem: which endpoints, users, regions or instances are affected, and exactly when it started; line that up against deploys, config changes, traffic shifts and dependency incidents.
  3. Use the telemetry: error rate, latency percentiles and saturation metrics to localise, logs filtered by correlation ID, and distributed traces to find the failing or slow hop.
  4. Form one hypothesis at a time and test it cheaply: compare a healthy and an unhealthy instance, reproduce in staging with production-like data, and add targeted logging if the evidence is missing.
  5. After the fix, confirm recovery in the same metrics and write a blameless postmortem whose action items include the alert or test that would have caught it earlier.

Follow-up

  • The error hits one request in a thousand and does not reproduce in staging. What next?
  • Memory on one service grows for days until it restarts. How do you find the leak?
  • How do you tell whether a deploy that went out at the same time is the cause or a coincidence?

What steps would you take to troubleshoot a failing deployment?

Medium · Problem-Solving / Case Studies

Approach

  1. Locate the failing stage: build, tests, artifact publish, deploy, container start, health check, or errors after traffic shifts; read that stage's pipeline log (for example in Jenkins) before guessing.
  2. Diff against the last good deployment: code, dependency versions and lockfile, base image, environment variables and secrets, infrastructure and database migrations.
  3. Check the usual suspects: a missing secret or env var, a migration that failed or locked a table, a port mismatch, a failing readiness probe, or a container OOMKilled by its memory limit; in Kubernetes, kubectl describe pod shows events and kubectl logs --previous shows the crashed container's output.
  4. Restore service first by rolling back to the last good artifact, then reproduce with the exact same image and configuration outside production.
  5. Prevent a repeat: build immutable artifacts once and promote them, use canary or blue-green rollouts with automatic rollback on failed health checks, and keep migrations backward compatible with the previous app version.

Follow-up

  • The database migration succeeded but the new app version fails. Can you roll back safely?
  • The build passes locally and fails in CI. Where do you look?
  • Only some pods in the new release fail. What does that suggest?

Suggested practice checklist

The plan follows the four reported rounds and the five question groups candidates report, putting coding first, then fundamentals and design, then debugging and behavioral stories. Each day ends with something you can check.

Day 1 — Map the loop and your stories

  • Write the four reported rounds in order and one line on what each covers, marking the stage you are least ready for
  • Write a project sheet for two or three projects: problem, your contribution, stack and one decision you would defend
  • Outline your version control answer: branching approach, merge versus rebase, and one recovery story

Deliverable: A one-page loop map, a project sheet and a written outline of the version control answer.

Day 2 — Coding: linked list and strings

  • Implement list reversal iteratively and then recursively in your chosen language (Java, C# or Python)
  • Solve the longest-substring problem with a sliding window and a hash map, stating the complexity of both the brute force and the final version
  • Write tests for empty input, one element and repeated characters

Deliverable: Two working solutions with complexity notes and a test file covering the edge cases.

Day 3 — Coding: sorting, dynamic programming, optimization, testing

  • Implement merge sort or quicksort and write a table of best, average and worst time and space cost
  • Solve one dynamic programming problem, writing the recurrence and base cases first, then memoized and bottom-up versions
  • Profile a slow function of your own and write the before and after measurement

Deliverable: A sort implementation with a complexity table, a dynamic programming solution with its recurrence, and a before-and-after measurement.

Day 4 — Fundamentals and API design

  • Write answers on object-oriented programming and on synchronous versus asynchronous code, each with a code example in your language
  • Write a code quality checklist covering reviews, tests, linting, naming and small functions
  • Design a REST endpoint for creating an order: request identity for safe retries, error codes and versioning

Deliverable: Two example-backed written answers, a code quality checklist and a one-page API contract.

Day 5 — System design and data storage

  • Draw a scalable web application on AWS or Azure: stateless tier, load balancer, cache, database, queue; mark the first bottleneck
  • Compare two storage options for a workload you choose, covering consistency, query pattern and scaling
  • Write a monolith-versus-microservices comparison, then work the practice SQL drills on concurrent creates and a live backfill
  • Describe a system you built and its hardest challenge in a structured outline

Deliverable: A labelled architecture diagram, a storage comparison table, a one-page monolith-versus-microservices note and an outline of your own system story.

Day 6 — Debugging, deployment and trade-offs

  • Write a production debugging runbook: what changed, reproduce, logs and metrics, bisect, fix, prevent
  • Write a failing-deployment checklist for a Jenkins-style pipeline: build, configuration, artifact version, health check, rollback
  • Talk through a technical problem from your work from start to finish, then a trade-off matrix for one decision

Deliverable: A debugging runbook, a deployment checklist and one recorded technical walkthrough with its trade-off matrix.

Day 7 — Behavioral rehearsal

  • Write STAR outlines for conflict, prioritization, a successful project, explaining to non-technical people, feedback and learning a technology quickly
  • Record each answer aloud and cut anything that does not state your own action or a result
  • Run a full mock mixing one coding problem, one design question and two behavioral questions

Deliverable: Six STAR outlines, six recorded answers and notes from one mixed mock.

Behavioral preparation for Bravotech

Candidate accounts list leadership and culture fit among the evaluation areas, and the final round is described as cross-functional, so behavioral prompts here cover collaboration, prioritization, communication and growth. Prepare stories where your own decision is visible and the result is checkable.

Discuss your experience with version control systems.

Medium · Technical / Domain Questions

Approach

  1. Prepare a real answer on three levels: daily workflow (feature branches, small commits, pull requests, review), recovery skills (revert versus reset, cherry-pick for a hotfix, git bisect to find the commit that broke something), and team practice (branch protection, CI on every pull request, tagging releases).
  2. Be ready to state the merge versus rebase trade-off: merge preserves true history, rebase gives a linear history but rewrites commits, so never rebase a branch others have pulled. Say which your team used and why.
  3. Tell one short story where you made the call: for example, you bisected a regression across many commits, or untangled a conflicted merge between two long-lived branches. Give what you did, what you checked afterwards and the result.
  4. Mention how version control connects to delivery: a Jenkins or similar pipeline that builds on each push, and how you roll back by reverting a commit rather than editing history on a shared branch.
  5. Avoid the answer that only lists commands. A list shows familiarity; a story about a bad merge, a lost commit or a release branch shows judgement.

Follow-up

  • When would you choose rebase over merge, and when is rebase unsafe?
  • A bad commit is already on the main branch and deployed. How do you undo it?
  • A feature branch has diverged for weeks from main. How do you bring it back with the least risk?

Describe a time when you had to resolve a conflict within your team.

Medium · Behavioral / Leadership

Approach

  1. Choose a conflict about a technical or process decision (an API shape, a code review standard, who owns a task), not a personality clash. State it in two sentences: who disagreed, what each side wanted, and what was at stake for the project.
  2. Show what you did first: asked the other person to explain their goal, found the real constraint underneath the position, and moved the discussion from opinion to evidence, such as a benchmark, a prototype or a past incident.
  3. Say how it ended: a compromise, a decision by the owner, or your change of mind. If you escalated, say you tried to resolve it directly first and what you asked the decision-maker to settle.
  4. Close with the result and the relationship afterwards: the delivery outcome, what changed in how the team decides things, and one thing you would do earlier next time.
  5. The story fails when the other person is the villain, when you never changed your own view, or when the resolution was that someone gave up.

Follow-up

  • What if the other person had still disagreed after you showed the evidence?
  • Looking back, were you partly wrong? What did you concede?
  • How did you work with that person after the decision?

How do you prioritize tasks when you have multiple deadlines?

Medium · Behavioral / Leadership

Approach

  1. Show a method, not a feeling. List every commitment with its real deadline, who is waiting on it, the cost of delay, rough effort and any dependencies. Order by cost of delay and by what unblocks others, not by who asked loudest.
  2. Give a concrete case: say three deliverables collided, which one you did first and why, which you split into a smaller first release, and which you renegotiated. Name the number of items and the actual trade.
  3. Make the trade-offs visible: tell stakeholders what will slip and offer options such as cutting scope, moving a date or getting help. Priority conflicts are settled with the people who own the priorities.
  4. Mention how you protect the plan: a visible task list, time reserved for interrupts and code review, and a rule for when a production issue pre-empts planned work.
  5. Avoid claiming you work longer hours as the strategy; it does not scale and hides the real decision.

Follow-up

  • Two managers both say their task is the top priority. What do you do?
  • You realise midway that you will miss one deadline. When and how do you say so?
  • How do you handle an urgent production issue in the middle of a sprint commitment?

Give an example of a successful project and your role in it.

Medium · Behavioral / Leadership

Approach

  1. Choose a project where your role is unambiguous and the outcome can be stated in numbers or facts: latency reduced, defects avoided, a launch date met, users onboarded. State the goal and your part in two sentences.
  2. Spend the bulk of the answer on your decisions: the design you chose and the alternative you rejected, a scope cut, a risk you raised early, a review you gave. Use I for your own actions and name teammates for theirs.
  3. Show leadership without a title: you unblocked someone, aligned product and QA on acceptance criteria, or documented a decision so the team could move without you.
  4. End with the result, what you learned and what you would change, such as an earlier load test or a smaller first release.
  5. The mistake is describing a team success with plural pronouns and no personal action, or choosing a project whose success you cannot measure.

Follow-up

  • Which part of the project was not your work, and who did it?
  • What was the hardest decision and what did it cost?
  • If you rebuilt it today, what would you do differently?

What strategies do you use to communicate complex technical information to non-technical stakeholders?

Medium · Behavioral / Leadership

Approach

  1. Start from the audience's decision, not the technology: lead with what they need to decide, the impact in their terms (cost, risk, date, customer effect), and your recommendation. Detail comes only when they ask.
  2. Name concrete tactics: replace jargon with an everyday analogy, draw a three-box diagram, give two or three options with cost, risk and timeline, and send a written summary afterwards.
  3. Check understanding rather than assuming it: ask them to restate the trade-off in their words, or ask what decision they would make from what you said.
  4. Use a real story, ideally with the teams candidates say engineers work with, such as explaining to product management why a feature needs a migration first, or to QA why a release had a rollback plan.
  5. The mistake is a story where the other person simply did not understand; show what you changed in your explanation when the first attempt did not land.

Follow-up

  • Explain microservices to a product manager in two sentences.
  • A stakeholder insists on a date you believe is infeasible. What do you say?
  • How did you know the explanation had worked?

How do you handle feedback and criticism?

Medium · Behavioral / Leadership

Approach

  1. Use one real piece of critical feedback about your work, not a disguised strength. Say who gave it, what exactly it was, and your first reaction honestly, then how you responded: listened, asked for a specific example, and checked your understanding before defending anything.
  2. Show the action and the lasting change: for instance, you adopted a checklist for pull requests after comments about missing tests, and later review comments on that issue stopped.
  3. Include a code review angle: how you separate blocking comments from style nits, how you reply with evidence when you disagree, and how you thank reviewers for catches.
  4. If you pushed back on feedback, show how you did it respectfully, with data or a small experiment, and what you did when the other person still disagreed.
  5. The answer fails if the feedback is trivial, if you were defensive and never changed, or if you cannot say what is different now.

Follow-up

  • Tell me about feedback you disagreed with. What did you do?
  • How do you give critical feedback in a code review?
  • What is the feedback you are working on right now?

Describe a time when you had to learn a new technology quickly to complete a project.

Medium · Problem-Solving / Case Studies

Approach

  1. Pick a story with a real deadline and a technology you genuinely did not know, ideally close to the listed stack, such as a cloud service, a web framework or a container tool. State what was new and what depended on it.
  2. Show a learning method: you scoped the minimum slice needed, read the official documentation, built a small throwaway prototype, and asked someone experienced to review your approach early.
  3. Cover risk control: tests around the new part, a pull request reviewed by someone who knew the technology, a limited rollout, and a note of what you were still unsure about.
  4. Give the result and the mistake: what shipped, what you got wrong the first time and how you found out, and how you shared what you learned afterwards.
  5. The mistake is a story about cramming facts. The story must show judgement about what to learn first, and how you made sure the result was safe.

Follow-up

  • How did you decide you knew enough to ship?
  • What did you get wrong at first?
  • How would you help a teammate pick up the same technology?