cswork / libraryOpen practice workspace

Interview guides · B Lab Global

B Lab Global Software Engineer Interview Guide

B Lab Global Software Engineer interview guide: reported questions, coding and system design prep, behavioral answer structures and a 7-day plan.

The 60-second brief

B Lab Global works on a global movement for an inclusive economy. Candidate descriptions of the Software Engineer role name two products, the B Impact Assessment and the Global Reporting Initiative, which companies use to measure their social and environmental performance. Engineers in this role are described as improving existing applications and adding new features, working alongside product management, design and operations colleagues.

This guide is for candidates interviewing for the Software Engineer role at B Lab Global. Descriptions of the role mention a language such as Python, Java or JavaScript, working knowledge of software frameworks, solid algorithms and data structures, and roughly two to five years of development experience. The guide covers the reported technical questions (languages, a hard problem, a recent project, code quality, version control, coding, system design, clean code), the four reported behavioral questions, and a plan that turns them into practice.

Candidates report an online assessment followed by several interviews that combine coding challenges, technical conversations and discussion of past experience and fit with the mission. No finer round order or stage length is reported, so confirm the sequence with your recruiter.

Focus areas

  • Behavioral Interviewing
  • Coding Interview Preparation
  • System Design

Overview

Candidate descriptions place software engineers on assessment and reporting products, the B Impact Assessment and the Global Reporting Initiative, which companies use to measure social and environmental performance. The reported duties are practical: design, build and test applications, refine requirements with product managers and designers, take part in code reviews, write documentation, and troubleshoot problems in running software. Typical projects are described as improving existing applications or adding features.

The reported questions are mostly open conversation: which languages you are most comfortable with and why, a hard technical problem you solved, a recent project and your role in it, how you keep code quality up, and how you use version control. Alongside them candidates describe coding challenges, system design and clean, maintainable code as topics. That makes two kinds of preparation: rehearsed, specific stories about your own work, and fluent fundamentals in one language (Python, Java and JavaScript are the examples given) with arrays, hash maps, sorting and basic complexity analysis.

The role is described as cross-functional, so the behavioral side deserves real effort. Four prompts are reported: a difficult team member, prioritising several deadlines, taking the lead on a project, and constructive criticism. Choose stories that show you working with product managers, designers or operations people, and prepare an honest, specific reason for wanting to work on tools that help companies measure their impact, because candidates also describe discussion of how your experience relates to the mission.

The format is only partly reported: an online assessment, then multiple interviews mixing technical and behavioral material. Candidates also mention variability in interviewer engagement and communication. Prepare answers that stand on their own: open with the headline, give two or three concrete details, close with the outcome, and ask the recruiter early what each stage covers and whether you will write code.

Where to focus your preparation

Candidates describe an online assessment followed by several interviews, but no detailed stage order is reported. The single entry below is a preparation focus covering everything reported.

Preparation focus

Candidates report an online assessment first, then multiple interviews that blend coding challenges, technical conversations and discussion of your past experience and the mission. Because no order or length is reported per stage, treat this as one preparation block: pick a primary language and practise coding while explaining your reasoning aloud, prepare walk-throughs of two real projects, and have behavioral stories ready. Ask the recruiter whether the online assessment is timed, which languages it allows, and whether later coding is written live.

What to demonstrate

  • Working code in a language you choose, with your reasoning explained as you go
  • How you describe past projects, your own role in them and the problems you solved
  • How you would design a system around user needs, and how you keep code clean and maintainable
  • Collaboration and communication, shown through your behavioral stories

How to prepare

  • Choose one of Python, Java or JavaScript and solve a few array, hash map and sorting problems in it while narrating aloud
  • Write one-page outlines for two projects: context, your role, key decisions, outcome and what you would change
  • Prepare a concrete answer on code quality and version control using a real pull request or release as the example
  • Rehearse the four reported behavioral prompts with one story each, plus one on working with a product manager or designer

Where candidates lose points

Answering the languages question with a list of everything you have touched

Name one primary language and give two concrete reasons tied to work you have done: its standard collections, typing, tooling or ecosystem. Say where it is a poor fit and which other language you would reach for. Python, Java and JavaScript are the examples listed for this role, so be ready to compare yours with one of them.

Describing a recent project as a team summary without your own role

The question asks what your role was. Write an outline with context, your part, two decisions you made and their trade-offs, the outcome and what you would change. Keep the same outline for the hard-problem question and swap in the debugging sequence.

Answering code quality and version control with buzzwords (tests, reviews, branches) and no example

Anchor each practice in something real: a test that caught a regression, a review comment that changed a design, a revert that restored a release. For version control cover small focused commits, branch and pull request flow, merge versus rebase and when you use each, and how you undo a bad change.

Working a coding challenge silently, or coding before agreeing the problem

The reported prompt asks you to explain your thought process. Restate the problem, give an example, say the brute-force approach and its complexity, then improve it while naming the data structure. Test on an empty input, a single element and duplicates before saying you are done.

Behavioral stories with no outcome, with blame, or with generic enthusiasm for the mission

Give every story a result and one lesson, and describe disagreements in terms of behaviour and evidence. For the mission, say specifically what draws you to software that helps companies measure impact, linked to work you have done, rather than repeating the phrase inclusive economy.

Questions & practice

Archive a resource graph without breaking live references or recursing

Medium · graph traversal · topological order · tenant isolation

Resources reference other resources within a tenant; for the largest tenant the reference table holds up to 2,000,000 nodes and 8,000,000 edges. Archiving a resource must archive everything reachable from it that nothing outside the set still references, refuse when a live external referrer exists, and terminate when references form cycles, which they legitimately do. Produce the archive order and the refusal list, targeting O(V+E). Say what stops the traversal crossing a tenant boundary, and why recursion is the wrong control structure at this size.

Approach

  1. Load the subgraph with the tenant predicate on both endpoints of the edge, not only on the side you started from. Scoping the left table alone is the classic cross-tenant leak: one mis-entered edge then pulls another tenant's resources into the traversal and, worse, into the archive.
  2. Traverse iteratively with an explicit stack. A 2,000,000-node graph can hold a chain deep enough to exhaust a native stack in the low tens of thousands of frames, and that failure is a process crash rather than an error you can return.
  3. Treat cycles as data rather than corruption: compute strongly connected components with Tarjan in O(V+E) using its own explicit stack, then condense. The condensation is a DAG, so a topological order over it gives the archive order, and every member of a component archives in one transaction because no order within a cycle is valid.
  4. Decide refusals with reverse edges. A candidate is archivable only if every in-edge originates inside the candidate set, so build the transpose or count in-degrees restricted to the visited set, and emit each blocked resource with the id of the external referrer, which is the only part of the answer an operator can act on.

Follow-up

  • The graph is read in one query and the archive writes a minute later. What can change in between, and how do you make the write safe?
  • The candidate set is 400,000 resources. Is that one transaction, and if not, what does a half-finished archive look like to a reader?

Track a rolling failure rate per destination for circuit decisions

Easy · sliding window · ring buffer · circuit breaker

The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.

Approach

  1. Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
  2. Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
  3. State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
  4. Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.

Follow-up

  • The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
  • A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?

Merge partitioned event streams into one ordered feed with bounded lateness

Hard · k-way merge · watermarks · out-of-order streams

The read-model service consumes 64 log partitions carrying about 4,000 events per second in total. Each partition is ordered within itself, but partitions drift by up to 30 seconds, and the activity feed must present a tenant's events in occurred_at order. Produce the merge. State its complexity, the buffer it requires in events and in bytes, what happens when one partition is idle, and what you do with an event that arrives after you have already emitted its position. Payloads average 1 KB.

Approach

  1. Merge with a min-heap over the 64 partition heads keyed on (occurred_at, event_id): O(log P) per event and O(n log P) overall. The tie-break on event_id is what makes the output deterministic when two partitions carry the same millisecond, which matters because the feed is paginated and a non-deterministic order reorders pages under the reader.
  2. Emitting the heap head is only correct once every partition has produced everything up to that timestamp, so the emit condition is a watermark: the minimum across partitions of the highest occurred_at seen, less the allowed lateness. Events are held until the watermark passes them, which is what turns individually ordered streams into a jointly ordered one.
  3. Size the buffer from the lateness rather than guessing: 4,000 events per second times 30 seconds is 120,000 buffered events, and at 1 KB each about 120 MB of heap. That number is the real price of the ordering guarantee and belongs in front of whoever asked for it.
  4. Handle the idle partition explicitly, because it fails the feed rather than corrupting it: a partition with no traffic never advances its own maximum, so the watermark freezes and output stops entirely. Either every partition emits a periodic idle marker carrying the broker's current time, or the watermark falls back to wall clock for a partition silent beyond a threshold.

Follow-up

  • The lateness budget is raised to five minutes. What is the new buffer, and what besides memory changes?
  • The consumer restarts. Where does it resume from, and what does the feed look like for the first 30 seconds?

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?

Replace offset paging on the resource feed with keyset

Easy · keyset pagination · composite index · sort order

resource holds resource_id, tenant_id, owner_user_id, title, body_ref, version, status ('draft','active','archived','deleted'), created_at, updated_at, deleted_at, with an index on (tenant_id, status, updated_at DESC, resource_id DESC). The listing endpoint returns active resources for one tenant, newest update first, 50 per page, today with LIMIT 50 OFFSET n. Tenants reach page 400 and rows are created while they read. Write the keyset query, define what the cursor carries and how it is encoded, and say which part of the index each predicate uses. Assume PostgreSQL 16.

Approach

  1. Name the two failures separately. OFFSET 20000 makes the server produce and discard 20,000 rows, so page cost grows with depth rather than with page size. Independently, any write that changes how many rows sort above the offset moves the window between two fetches, and the direction decides which anomaly you get: an insert lands at the head of updated_at DESC and pushes already-returned rows down past the boundary, so they are returned a second time; a delete above the offset, or a row whose updated_at is bumped above the cursor, pulls rows up and one is never returned at all. Nothing in the response reveals either.
  2. Write the seek: WHERE tenant_id = $1 AND status = 'active' AND (updated_at, resource_id) < ($2, $3) ORDER BY updated_at DESC, resource_id DESC LIMIT 50. The row-value comparison is one index range rather than a disjunction, and both columns are NOT NULL, which is what makes that comparison well defined.
  3. Map each predicate onto the index: tenant_id and status are equality on the leading columns, (updated_at, resource_id) is the range, and the ORDER BY matches the index order so no Sort node appears and the scan stops after 50 rows. The DESC in the definition only matters for mixed directions — a plain ascending btree on the same columns is read backwards for this query.
  4. Put both sort columns in the cursor and nothing the client can tamper with into another tenant: base64 of (updated_at, resource_id), validated server-side, with tenant_id taken from the principal.

Follow-up

  • The client asks for 'jump to page 400'. What do you offer instead, and what does the honest version cost?
  • Sort order becomes user-selectable across four columns. How many indexes is that, and which would you refuse to add?

What programming languages are you most comfortable with, and why?

Medium · Technical / Domain Questions

Approach

  1. Name one primary language and one secondary, and tie each to a project you shipped in it. The role requirements candidates describe list Python, Java and JavaScript, so if you know any of them, lead with it.
  2. Give reasons that are true of the language itself, not just that you like it. Java: static typing and the JVM's mature tooling. Python: fast iteration and a large standard library. JavaScript/TypeScript: one language in the browser and on Node.
  3. Say where your favourite language is weak. In the standard CPython build, the GIL stops CPU-bound threads from running in parallel, so you would use multiprocessing or native extensions. JavaScript runs on a single-threaded event loop, so CPU-heavy work blocks it unless you move it to worker threads.
  4. Show how you choose a language: team familiarity, available libraries, the runtime the deployment already uses, and hiring. Say you would not rewrite a working service just to switch languages.

Follow-up

  • What is something your favourite language makes harder than it should be, and how do you work around it?
  • How would you get productive in a language this team uses that you have not written professionally?
  • In your main language, how do you handle concurrency for I/O-bound work compared with CPU-bound work?

Describe a challenging technical problem you encountered and how you solved it.

Medium · Technical / Domain Questions

Approach

  1. Pick a problem where you did the diagnosis yourself, and open with the symptom and its impact: who was affected, how often, and how you found out (an alert, a user report, a failing test).
  2. Walk through how you narrowed it down. Reproduce it first, then form hypotheses and test the cheapest one first, using logs, metrics, a debugger, or git bisect to find the commit that introduced it.
  3. State the root cause precisely: a race condition, an N+1 query, a missing index, a timezone or encoding bug, or a cache that was never invalidated. Explain why the obvious fix would only have hidden it.
  4. Close with the fix, how you checked it worked (a regression test, a before/after metric), and what you changed so it would not happen again. Use 'I' for your own actions and credit teammates by role.

Follow-up

  • Which hypothesis did you rule out first, and what evidence ruled it out?
  • If the same symptom came back next month, what would you check first?
  • What would have caught this before it reached production?

Can you explain a recent project you worked on? What was your role?

Medium · Technical / Domain Questions

Approach

  1. Open with the problem and the users in two sentences, then give the architecture in one: the client, the services, the data store and any queue or third-party API.
  2. Separate your own work from the team's. Name the components you designed or wrote, the decisions you owned, and the ones you only reviewed.
  3. Describe one real trade-off you made: the alternative, why you did not pick it (cost, latency, consistency, delivery date), and what it cost you later.
  4. Finish with a result you can check, such as a shipped feature, adoption, a latency or error-rate change, or time saved, plus one thing you would change now.

Follow-up

  • Sketch the data model for the part you owned. Which table or entity changed most often?
  • What broke after launch, and how did you find out?
  • If you had to hand this project to a new engineer tomorrow, what would they need to understand first?

How do you ensure the quality of your code?

Medium · Technical / Domain Questions

Approach

  1. Describe layered checks, cheapest first. A formatter and linter (Prettier/ESLint, Black/Ruff), a type checker where the language supports one (TypeScript, mypy), then automated tests, all running in CI as a required gate before merge.
  2. Explain your testing mix. Use many fast unit tests on pure logic, fewer integration tests against a real database or service container, and a small number of end-to-end tests on the main user flows. Add a regression test for every bug you fix.
  3. Treat coverage as a signal, not a target. High line coverage can still miss boundary cases (empty input, nulls, duplicates, time zones), so say which cases you write tests for on purpose.
  4. Keep pull requests small, with a clear description, so review is meaningful. After deploy, use logging, error tracking and metrics to catch what tests missed, plus a rollback or feature flag.

Follow-up

  • How do you test code that calls an external API or a payment provider without hitting the real thing?
  • A test fails intermittently in CI. What do you do with it?
  • When would you merge code with lower test coverage, and what would you do instead?

What are some best practices you follow for version control?

Medium · Technical / Domain Questions

Approach

  1. Make small commits that each do one thing, with messages that say why the change was made, so that git log, git blame and git bisect stay useful.
  2. Use short-lived feature branches merged through pull requests into a protected main branch. CI must pass and at least one review is required before merging.
  3. Know the trade-offs. Rebase gives linear history but rewrites commits, so never rebase a branch others have already pulled. Merge commits keep the true history. Squash merges give one commit per pull request but lose the intermediate steps.
  4. Undo safely. On a shared branch, git revert adds a new commit that reverses a change, whereas git reset moves the branch pointer and rewrites history, so keep reset for local, unpushed work.
  5. Keep secrets and build output out of the repo with .gitignore and pre-commit checks. If a credential is ever pushed, rotate it, because deleting it from history does not undo the exposure.

Follow-up

  • Walk through resolving a merge conflict in a file you and a teammate both changed.
  • A regression shipped somewhere in the last 40 commits. How do you find the commit that caused it?
  • You discover an API key was committed three weeks ago. What exactly do you do?

Coding Skills – Be prepared to solve coding challenges and explain your thought process.

Medium · Technical Proficiency

Approach

  1. Restate the problem and confirm the input size, value ranges and edge cases (empty input, duplicates, negative numbers) before writing code, then work one small example by hand.
  2. State a brute-force solution and its complexity out loud, then name what makes it slow and the pattern that removes it. A hash map gives O(1) average lookups, which turns many O(n^2) pair searches into O(n). Two pointers or binary search work on sorted input. A sliding window handles contiguous subarrays. BFS finds shortest paths in an unweighted graph. A heap of size k gives top-k in O(n log k).
  3. Write the code in the language you know best, with clear names and small helper functions, and explain each block as you write it rather than coding in silence.
  4. Test by tracing your example and then the edge cases through the code. Fix off-by-one errors and empty-input handling, then state the final time and space complexity.

Follow-up

  • What is the time and space complexity of your solution, and can you reduce the extra space?
  • How would your solution change if the input arrived as a stream too large to hold in memory?
  • Which test case would most likely break your first version, and why?

System Design – Discuss how you would design systems to meet user needs.

Medium · Technical Proficiency

Approach

  1. Start with requirements. List the user actions to support (for a multi-step questionnaire that organisations fill in and submit: save progress, upload supporting documents, submit, view results), then the non-functional needs: number of users, read/write ratio, and how stale data may be.
  2. Define the API and data model before drawing boxes. A relational database fits structured answers with clear relationships (organisation, questionnaire version, question, answer). Keep uploaded files in object storage and store only their keys in the database.
  3. Lay out the components. Put stateless application servers behind a load balancer so they can scale horizontally. Add a cache for read-heavy, rarely changing data such as question definitions. Use a background job queue for slow work like scoring or report generation, so a request does not wait on it.
  4. Handle correctness explicitly. Use an idempotency key on submit so a retried request does not create two submissions. Add a version column for optimistic concurrency when two people edit the same record. Keep each submission tied to a questionnaire version so later changes do not alter past results.
  5. Finish with failure and growth. Cover what happens if the queue or database is unavailable, how you would monitor it (error rate, latency, queue depth), and what you would scale first if traffic grew tenfold.

Follow-up

  • Two colleagues edit the same answer at the same time. What does each of them see, and how does your design decide which edit wins?
  • The scoring rules change. How do you re-score past submissions without blocking new ones?
  • Which part of this design fails first at ten times the traffic, and what do you change?

Best Practices – Explain your approach to writing clean and maintainable code.

Medium · Technical Proficiency

Approach

  1. Write for the reader. Use names that say what a thing is or does, and keep functions short with one responsibility, so a change touches one place. Use comments to explain why, not to repeat what the code says.
  2. Keep side effects at the edges. Pure functions for business logic and dependencies passed in (dependency injection) let you unit-test logic without a database or network.
  3. Be careful with abstraction. Duplication is cheaper than the wrong abstraction, so extract shared code once the pattern has repeated and is stable (the 'rule of three'), not after the first copy.
  4. Make errors explicit. Validate input at the boundary, fail with clear messages, and never swallow exceptions silently. Let a shared formatter and linter settle style questions so review time goes to logic.
  5. Refactor in small steps covered by tests, separate from behaviour changes in the same pull request, so reviewers can check each step on its own.

Follow-up

  • Give an example of code you refactored. What made it hard to change before, and how did you make sure behaviour did not change?
  • When does removing duplication make code worse?
  • A reviewer and you disagree about a design choice in your pull request. How do you settle it?

p99 jumped on one listing filter while p50 stayed flat

Medium · query planning · composite index · percentiles

After a release that added an owner_user_id filter to the resource listing, p99 rose from 90 ms to 1.9 s while p50 stayed at 40 ms. Traffic and row counts are unchanged. resource carries the index (tenant_id, status, updated_at DESC, resource_id DESC). The new query filters tenant_id and owner_user_id, orders by updated_at DESC, resource_id DESC, and takes 20 rows. On PostgreSQL, explain the shape of the regression, prove it from a query plan, and give the index you would add.

Approach

  1. Start from the shape. A flat p50 with a moved p99 means a subset of requests changed cost, not all of them, so the first job is naming the subset. Bucket the endpoint's latency by the tenant's row count; the natural hypothesis is that large tenants are a small share of requests and all of the tail.
  2. Get the plan for the new query on a large tenant with EXPLAIN (ANALYZE, BUFFERS). Expect an index scan over the tenant's range, a filter discarding most of it, then a Sort feeding the Limit, possibly reporting Sort Method: external merge Disk. Read actual rows on the scan node, not estimated.
  3. Explain why the existing index cannot serve it. A composite B-tree is seekable only as a left prefix, and with no equality predicate on status the scan cannot treat updated_at as an ordering, because rows in the tenant's range are ordered by status first. Everything matching must be read and sorted before LIMIT 20 can apply, so a tenant with 400,000 rows pays 400,000 rows to return 20.
  4. Add (tenant_id, owner_user_id, updated_at DESC, resource_id DESC). Equality on the first two columns leaves the index ordered by updated_at within that pair, so the plan becomes an index scan that stops after 20 rows with no Sort node. PostgreSQL can scan a B-tree backwards, so the DESC markers matter only if the two sort columns ever disagree in direction; keeping them explicit documents the order the keyset cursor depends on.

Follow-up

  • The endpoint paginates with OFFSET. What does page 500 cost with your index, and what does the keyset version cost?
  • How would you have caught this before release, given that a 10,000-row seed database produces the same plan shape at an unnoticeable cost?

Suggested practice checklist

Each day targets one cluster of the reported questions: language and project stories, code quality and version control, coding, system design, behavioral stories, then a mixed run.

Day 1 — Confirm the format and fix your language

  • Email your recruiter asking for the stage order, whether the online assessment is timed, which languages it allows and whether later coding is live
  • Choose your primary language from Python, Java or JavaScript and write a short answer naming two concrete reasons and one weakness
  • Review that language's standard collections: list or array, hash map, set, queue and sorting, with their complexities

Deliverable: A sent recruiter email, a written answer to the language question, and a one-page collections and complexity cheat sheet

Day 2 — Project walk-through and hard-problem story

  • Pick two recent projects and outline each: context, your role, two key decisions, trade-offs, outcome and what you would change
  • Write the hard-problem story as a debugging sequence: symptom, hypothesis, evidence, fix, how you confirmed it
  • Say each outline aloud and cut anything that does not show your own contribution

Deliverable: Two project outlines and one hard-problem outline, each spoken through once

Day 3 — Code quality, clean code and version control

  • Write your code-quality answer with one real example for each of: tests, code review, static checks and documentation
  • List your version-control habits: small commits, branching and pull requests, merge versus rebase, reverting, resolving conflicts
  • Reopen one of your own old pull requests and write three things you would now change for readability or maintainability

Deliverable: A one-page answer sheet for code quality, version control and clean code, plus an annotated pull request

Day 4 — Coding challenges, narrated

  • Run each solution on empty, single-element and duplicate inputs before you call it finished

Deliverable: Two working solutions in your chosen language with a spoken explanation and listed edge cases

Day 5 — System design around user needs

  • Take a practice scenario: a self-assessment app where an organisation answers question sets and receives a report. Write requirements, users, data model and read and write paths
  • Sketch the components (API, storage, background report generation) and name the trade-offs you made, including consistency and what happens when a dependency fails

Deliverable: One design diagram with written trade-offs and a worked keyset paging query

Day 6 — Behavioral stories

  • Write a story outline for each reported prompt: difficult team member, multiple deadlines, taking the lead, constructive criticism
  • Add outcome and lesson to each, and remove any sentence that blames a person rather than describing behaviour
  • Prepare one story about working with a product manager, designer or operations colleague to change a requirement, and an honest reason for wanting to work on impact measurement tools

Deliverable: Four story outlines with outcomes and lessons, one cross-functional story and a spoken mission answer

Day 7 — Mixed rehearsal

  • Run a full mock: language question, project walk-through, one coding problem aloud, one design and two behavioral prompts
  • Write the questions you will ask the recruiter or team about the stages, the team's work and how engineers collaborate with product and design

Deliverable: A recorded or written mock run with a list of weak spots and a final question list

Behavioral stories for B Lab Global

Candidates report behavioral questions on collaboration, priorities, taking charge and feedback, plus discussion of how past experience relates to the mission. The role is described as working with product management, design and operations, so choose stories where the result depended on other people and say what you personally did.

  1. Tell me about a time you worked with a product manager or designer to change a requirement.
  2. What draws you to building software that helps companies measure their impact?

Tell me about a time you had to work with a difficult team member. How did you handle it?

Medium · Behavioral / Leadership Questions

Approach

  1. Choose a conflict about how work got done (review turnaround, unclear ownership, missed handoffs), not a personality clash. Describe the behaviour and its effect on the project, never the person's character.
  2. Show your first move was direct: a private one-to-one to understand their constraints. For example: I asked what was blocking them and found they were never told about the interface change.
  3. Describe the concrete agreement you reached, such as review-response expectations, a written interface contract or a split of ownership, and how you checked it held in the following weeks.
  4. Give the outcome in plain terms (delivery back on track, fewer blocked reviews) and say what you learned. Escalation to a manager is fine only as a later step, with what you tried first.
  5. The mistake that sinks it is a story where you are the hero and the colleague the villain, or where you went to the manager first and nothing changed.

Follow-up

  • What would you have done if that conversation had not worked?
  • How did you keep the project moving while it was unresolved?
  • What did you learn about how they preferred to work?

How do you prioritize tasks when you have multiple deadlines?

Medium · Behavioral / Leadership Questions

Approach

  1. Name a real period with competing deadlines and list each commitment with its due date, who was waiting on it, and the cost of it slipping. Rank by cost of delay and by what blocks other people, not by effort.
  2. Show a trade-off, not just a method: say what you deferred or cut and why. For example: I shipped the bug fix first because users were blocked, and moved the refactor a week.
  3. Describe how you communicated. Tell the affected product manager or colleague early, offer options (reduce scope, move the date, get help) and let them choose, instead of quietly missing a date.
  4. Close with what happened to the deferred item and how you now guard against the same overload, such as a weekly list review or flagging conflicts at planning.
  5. The mistake that sinks it is a generic answer (I make a list and work hard) with no ranking criteria, no story and no sign that you ever said no.

Follow-up

  • What if two stakeholders each insisted their deadline came first?
  • How do you tell a product manager that something will slip?
  • What happened to the task you deferred?

Describe a situation where you took the lead on a project. What was the outcome?

Medium · Behavioral / Leadership Questions

Approach

  1. Pick a project where you set direction, even without a formal title. State the goal and your role in two sentences, then spend the time on how you led.
  2. Cover the mechanics: how you broke the work into pieces, who took what, how you kept requirements clear with the product manager or designer, and how often the group synced and reviewed code.
  3. Include one thing that went wrong or one disagreement, and how you resolved it. Without a setback the story sounds like a summary rather than leadership.
  4. Give the outcome concretely: what shipped, what improved for users or the team, what you would change. Do not invent numbers; if you have a real measure, give it.
  5. The mistake that sinks it is describing the team's achievement with the word we throughout and never saying what you personally decided.

Follow-up

  • How did you handle a teammate who fell behind?
  • What decision did you make that others disagreed with?
  • What would you do differently if you led it again?

How do you handle constructive criticism?

Medium · Behavioral / Leadership Questions

Approach

  1. Use one specific piece of feedback, ideally from a code or design review, and quote the substance of it (for example, that my pull requests were too large to review properly).
  2. Describe your first reaction honestly and what you did with it: asked clarifying questions, checked whether the feedback was right, and separated it from how it felt.
  3. State exactly what you changed in your behaviour (smaller pull requests, tests added before review, clearer commit messages) and the evidence it stuck, such as faster reviews or fewer review rounds.
  4. End with how you now seek feedback early, for example sharing a design sketch before writing code, which fits a role that includes code reviews and documentation.
  5. The mistake that sinks it is a disguised strength (I care too much about quality) or a story where you defended yourself and nothing changed.

Follow-up

  • Tell me about feedback you disagreed with. What did you do?
  • How do you give critical feedback to a peer in a code review?
  • How do you ask for feedback before something ships?