Interview guides · Bravissimo Ltd
Bravissimo Ltd Software Engineer Interview Guide
Bravissimo Ltd Software Engineer interview guide: reported rounds, JavaScript, basket persistence and stock transfer questions, and a 7-day prep plan.
The 60-second brief
Candidates describe Bravissimo Ltd as a retailer whose online presence runs on cloud-based platforms that connect customers to products, from browsing through checkout. The Software Engineer role is reported to work on that layer: refining the website user journey, keeping inventory data in sync, handling how a shopping basket is persisted, and taking part in the continuing move of the company's cloud infrastructure to newer approaches. The reported requirements put JavaScript and cloud experience first, with e-commerce or retail-tech background and agile working listed as extras.
This guide is for candidates applying as a Software Engineer at Bravissimo Ltd. It covers the three reported stages, the seven reported questions (two on coding practice and JavaScript, two on data design and data handling, three on motivation and work history), how to approach each one, and a seven-day plan that finishes with a full mock run.
Candidates report three stages over roughly 3-5 weeks: Application Review, Remote Interactions, and an On-site Assessment that includes group exercises and presentations.
Focus areas
- Persisting Data (Shopping Basket Persistence)
- Preparing a Technical Solution to a Specification
- JavaScript
Overview
The work candidates describe is the software behind an online retail operation. Three data problems keep coming up: where a shopper's basket lives between visits, how stock figures stay correct when goods move between locations, and how data flows between systems. Layered on that are two themes from the requirements: strong JavaScript, and experience of cloud environments. Preparing well means being able to reason about state that must survive a closed browser tab, and about numbers that must stay consistent when two updates arrive together.
The reported questions fall into three groups. Two ask for your own position: what you count as good coding practice, and how you approach JavaScript development. Two are small design problems: persisting items in an online shopping basket, and handling stock transfers between locations. Three are about you: why this company, what draws you to its culture and business model, and a walk through your employment history with the lessons you took from each role. The first group needs opinions backed by concrete code habits, the second needs a structured design answer with failure cases, the third needs a prepared narrative that is specific rather than flattering.
Candidates also report a format that rewards structure over improvisation: a mix of remote conversations and in-person assessment, with written technical tests, group exercises, and a presentation of a solution prepared to a brief. Some report writing code on paper. So the plan below spends as much time on explaining reasoning aloud, writing without an editor, and outlining a short presentation as it does on the technical content itself.
The Bravissimo Ltd interview process
Candidates describe three stages, and the reported detail grows as the loop goes on: the first is a review of your application, the second is remote, and the third is an in-person assessment with several formats.
Application Review
Candidates describe this stage as a review of your application for qualifications and fit. No questions are reported for it. The requirements candidates list for the role are the yardstick to prepare against: JavaScript proficiency, experience in cloud environments, an understanding of software development lifecycle practice, and, as extras, e-commerce or retail-tech experience and agile team working. Treat your CV and any application answers as the material that decides whether you move on, and make sure every line can be defended in conversation later.
What to demonstrate
- Fit between your experience and the listed requirements: JavaScript, cloud, lifecycle practice
- Whether your background shows e-commerce, retail-tech or agile team experience
- Whether your application gives a clear account of your career so far
How to prepare
- Map each requirement (JavaScript, cloud environments, lifecycle practice, e-commerce, agile) to one CV line with a concrete project behind it
- Write out your employment history as a short narrative with one lesson per role, since the same story is a reported question later
- Prepare a specific reason for applying to this retailer, grounded in what you have read about its products, so it can be reused when the question comes up
Remote Interactions
Candidates describe remote discussions that look at technical skills and how you would fit the team. The reported technical questions give the material to rehearse: your definition of good coding practice, your approach to JavaScript development, how to persist the items in an online shopping basket, and how to handle stock transfers between locations. Because the format is a conversation rather than a long coding session, the skill being exercised is explaining a design or a habit clearly in words, with the trade-offs said out loud.
What to demonstrate
- Technical skills as they come across in a remote conversation
- Team fit, as reported for this stage
- Ability to explain technical choices clearly and in a logical order
How to prepare
- Rehearse a spoken answer on your JavaScript approach: modules, asynchronous code and error handling, testing, and what you would refuse to merge
- Talk through basket persistence aloud: guest and signed-in baskets, the data stored per line, merging on login, expiry, and what happens when a price or stock level changes
- Talk through a stock transfer aloud: both sides of the move as one atomic change, an in-transit state, retries that must not double-apply, and an audit trail
On-site Assessment
Candidates report this as the longest and most varied stage, held in person and possibly lasting a full day. Reported formats include group exercises, a written technical test, a solution prepared on the spot to a project brief and then presented, and an office tour. Practical programming exercises and writing code on paper are also mentioned. The mix means three separate skills: producing correct, readable code without an editor, presenting a design with a clear structure, and working with other candidates rather than competing with them.
What to demonstrate
- Working code written under assessment conditions, on paper or live
- A solution prepared to a specification and presented clearly, including business impact
- Collaboration in group exercises
- Motivation for the company and the quality of your explanation of your own history
How to prepare
- Write small JavaScript functions by hand (a basket total with quantity limits, a stock move that rejects negative stock) and trace them with a test case before saying you are done
- Take a one-paragraph brief and practise producing an outline in a fixed structure: constraints, chosen design, one alternative rejected, risks, and what it means for the business
- Practise a group exercise role: summarise, ask for missing constraints, and credit others' points, rather than monopolising or staying quiet
Where candidates lose points
Answering the basket persistence question with one storage choice and nothing about the shopper's journey
Cover the full lifecycle: a guest basket before login, a signed-in basket, the merge when the two meet, expiry of abandoned baskets, storing item and quantity rather than a frozen price, and what the shopper sees when stock or price changes before checkout.
Describing a stock transfer as two independent updates, one subtracting from the source and one adding to the destination
Say the two sides must succeed or fail together, for example in one transaction or through a recorded transfer with an in-transit state. Add idempotent retries so a repeated message does not move stock twice, a rule that stock cannot go negative, and a log of every movement.
Staying silent while writing code on paper or in a live exercise
Narrate the plan before writing, name the inputs and edge cases (empty basket, zero or negative quantity, unknown item), and trace one example through your code before saying it is done. Candidates report that explaining the reasoning matters as much as the answer.
Giving a motivation answer that would fit any employer, such as praising the culture without examples
Tie your interest to the retail and e-commerce engineering problems candidates describe for this role, and to a concrete experience of your own. Make sure the answer to why this company and the answer on culture are different and not repeated.
Handling the group exercise or on-the-spot presentation as an individual performance
In the group, summarise others' points, ask about constraints, and move the discussion forward. For the presentation, use a fixed structure (constraints, design, rejected alternative, risks, business impact) so a partial solution still reads as organised.
Questions & practice
What are your definitions for good coding practices?
Medium · Technical Fundamentals and Coding
Approach
- Give a short, defensible definition rather than a list of slogans: code is good when another engineer can read it, change it safely and see it fail loudly. Then back each part with a concrete practice.
- Readability: intention-revealing names, small functions with one responsibility, early returns instead of deep nesting, and no magic numbers (a named constant such as FREE_DELIVERY_THRESHOLD_PENCE instead of 5000).
- Safety to change: automated tests on behaviour at the boundaries (unit tests for pure logic, a few integration tests around I/O), small reviewable pull requests, and formatting and linting enforced by tooling such as ESLint and Prettier so reviews discuss design, not whitespace.
- Failing loudly: validate input at system edges, never swallow errors in an empty catch, log with enough context to reproduce, and handle async rejections explicitly.
- Name the trade-off: DRY against premature abstraction. I duplicate twice and extract on the third use, because a wrong shared abstraction costs more than two similar functions.
Follow-up
- How do you get a team to adopt these practices without every review turning into a style argument?
- When have you knowingly shipped code that broke one of your own rules, and what did you do about it afterwards?
- Show me a function you would refactor: what would you change first, and how would you prove behaviour did not change?
Can you explain your approach to JavaScript development?
Medium · Technical Fundamentals and Coding
Approach
- Structure the answer around how you write, type, test and ship JavaScript: const by default and let when reassigning (both block-scoped, unlike function-scoped and hoisted var), strict equality (=== never coerces types), and ES modules with small, focused files.
- Show you understand the runtime: the event loop runs all queued microtasks (Promise callbacks) before the next macrotask (setTimeout), so heavy synchronous work blocks rendering and I/O; I chunk or move it to a worker.
- Async handling: async/await with try/catch at the right level; Promise.all rejects as soon as any input rejects, so I use Promise.allSettled when partial results are acceptable, and I always handle rejections.
- Correctness traps relevant to retail code: 0.1 + 0.2 !== 0.3 in floating point, so I hold money as integer pence and format only for display; I avoid mutating shared arrays and objects in place and return new ones instead.
- Quality loop: TypeScript or JSDoc types for contracts, ESLint for bug-prone patterns, unit tests with Jest or Vitest, and a build that fails on type or lint errors.
Follow-up
- What does this log, and why: console.log('a'); setTimeout(() => console.log('b'), 0); Promise.resolve().then(() => console.log('c')); console.log('d');
- How does
thisbehave in an arrow function compared with a regular function passed as a callback? - Three API calls run in parallel and one fails: how do you show the results that succeeded and report the failure?
How would you handle complex data scenarios, such as stock transfers between locations?
Medium · Technical Fundamentals and Coding
Approach
- Model stock as a ledger, not a single overwritten number: a stock_movement table (sku, location, delta, reason, transfer_id) and a balance table updated in the same transaction, so on-hand is a fast read and every unit has an audit trail.
- Treat a transfer as a state machine: requested, dispatched (decrement source, add to an in-transit location), received (decrement in-transit, increment destination), cancelled. In-transit stock is then counted once and never available at both ends.
- Make each step atomic: inside one transaction run UPDATE balance SET qty = qty - n WHERE sku = ? AND location = ? AND qty >= n and check that one row changed, so a concurrent sale at the source cannot drive stock negative; lock rows in a fixed order (for example by location id) to avoid deadlocks.
- When the source and destination live in different systems there is no shared transaction: use an outbox table written with the movement, deliver messages at least once, and make consumers idempotent on transfer_id plus step so a retry cannot apply twice.
- Edge cases: partial or damaged receipt (record the discrepancy as its own movement, never edit history), cancelling after dispatch, and a scheduled reconciliation comparing ledger sums with physical counts.
Follow-up
- The destination scans 18 units but 20 were dispatched: how is that recorded, and who sees the difference?
- Should units in transit count as available for online orders, and what changes if they do?
- The dispatch message is delivered twice: walk me through why stock is only moved once.
Why do you want to join Bravissimo Ltd specifically?
Medium · Behavioral and Role Motivation
Approach
- Treat this as a motivation question despite where it is filed: answer in three parts, the business, the engineering work, and your own fit, each with something specific.
- Business: show you have used the company's website and know what it sells and how; candidates describe a retailer that sells online and also moves stock between locations, so mention the link between the online shop and physical stock.
- Engineering work: connect to the problems candidates report for this role, such as shopping basket persistence, stock transfers and inventory data, and say which of them you have worked on or want to work on.
- Fit: one concrete piece of your history in JavaScript or cloud work that maps onto that work, ending with what you want to learn next.
- Avoid the answer that fits any employer ('great culture, good opportunity') or that talks only about what you gain; check it by asking whether it would still make sense with another company's name in it.
Follow-up
- What would you change first in the online shopping journey, and how would you measure whether it helped?
- Why a retail business rather than a pure technology company?
- Which part of this role do you expect to find hardest, and how would you get up to speed?
Write the update path that detects a concurrent edit
Medium · optimistic concurrency · transactional outbox · audit history
resource carries version INT NOT NULL DEFAULT 1. resource_revision holds revision_id, resource_id, version, actor_user_id, change_kind, patch JSONB, request_id, created_at with UNIQUE (resource_id, version). outbox_event holds aggregate_type, aggregate_id, aggregate_version, event_type, payload, status. A PUT carries the version the client read. Write the exact statements for the single transaction that applies the edit, records the revision and enqueues 'resource.updated', and give the handler's branch on zero affected rows. Then say what PostgreSQL 16 does under READ COMMITTED when two of these updates hit one row at once.
Approach
- One transaction, three writes, no network call inside it: UPDATE resource SET title = $3, version = version + 1, updated_at = now() WHERE resource_id = $1 AND tenant_id = $4 AND version = $2; then INSERT the resource_revision row at version $2 + 1; then INSERT the outbox_event row at the same aggregate_version. The event goes to a table rather than a broker because no transaction spans both.
- Branch on the affected-row count before doing anything else. Zero has three causes — stale version, wrong tenant, row gone — so re-read once and map to 409 carrying the current version, or 404 for an id outside the caller's tenant, which also stops the endpoint confirming that another tenant's id exists.
- State the engine behaviour instead of assuming it. Under READ COMMITTED the second UPDATE blocks on the row lock, and when the first commits PostgreSQL re-evaluates the WHERE clause against the newly committed row, so the version predicate now fails and the statement reports zero rows. Under REPEATABLE READ the identical collision raises SQLSTATE 40001 instead, so the handler must fold both shapes into one conflict response.
- Keep UNIQUE (resource_id, version) even though the predicate already serialises writers. It is what makes a lost update unwritable if any other path ever reaches the revision table, and it converts a logic bug into 23505 rather than into a silently missing history row.
Follow-up
- A client sends the version it read ten minutes ago and the resource has moved three versions. What is in your 409 so it can resolve the conflict without a full re-fetch?
- Two editors, two disjoint fields, no overlap. Does your answer still refuse the second write, and should it?
How would you architect a solution for persisting items in an online shopping basket?
Medium · Technical Fundamentals and Coding
Approach
- Clarify scope first: guest and signed-in shoppers, whether the basket must follow a customer across devices, and how long an abandoned basket is kept. That decides between client-only and server-side storage.
- Client-only (localStorage) survives a restart but is per browser and per device; a cookie is capped at about 4 KB and travels with every request. I keep only a basket id in a cookie and store contents server side: basket(id, customer_id, updated_at, expires_at) plus basket_line(basket_id, sku, quantity) with a unique key on (basket_id, sku), or a key-value store with a TTL for hot baskets.
- Writes are idempotent: 'set quantity of SKU to n' as an upsert instead of 'increment', so double clicks and retries do not double-add; a version column with a conditional update handles two tabs editing at once.
- Price and stock are not trusted from the basket: I re-price and re-check availability on every view and at checkout, and reserve stock at checkout rather than on add-to-basket, so idle baskets cannot lock inventory.
- Edge cases: merging a guest basket into a saved basket at sign-in (union by SKU, cap quantity at what is available), discontinued SKUs, expiry cleanup of abandoned baskets, and graceful behaviour when the basket store is unavailable.
Follow-up
- A guest with three items signs in to an account that already holds two of the same SKUs: what does the merged basket contain, and why?
- An item's price drops or it sells out while it sits in someone's basket: what does the shopper see, and when?
- How would you change the design if baskets had to be readable by a store or call-centre system too?
Choose what to break when replication lag reaches forty seconds
Hard · replication lag · read-after-write · consistency vs availability
Reads are served from two replicas: 14k requests/second, about 85% absorbed by cache, so roughly 2.1k reads/second reach the database. Writes go to the primary at 1.2k/second. A tenant's backfill drives replication lag from under 100 ms to 40 seconds and it is still climbing. Sessions that have just written are pinned to the primary. Decide, endpoint class by endpoint class, whether to serve stale, fail, or route to the primary, and justify each choice with the load it adds to the primary. Then state what you would have built beforehand.
Approach
- Establish blast radius before cause, because mitigation and diagnosis have different deadlines. The decisive arithmetic is what happens if the database reads move to the primary: 2.1k reads/second on top of 1.2k writes/second roughly triples its operation count, on the node already absorbing the backfill that caused this. Reads and writes are not equal in cost, so treat that as an argument against a blanket move rather than as a capacity model - but it is enough to rule out routing everything to the primary.
- Classify endpoints by what staleness costs, not by how important they feel. Reads whose staleness is invisible - listings, search, counters - stay on the replica and return the watermark so the client can tell. Reads that immediately follow that same session's write keep their primary pin, which is a small bounded slice of traffic rather than the whole 2.1k/second. Reads that feed a decision with a side effect - authorisation, quota, the read half of a read-modify-write - must not be stale at all, because a 40-second-old permission row is the stale-permission failure wearing a different costume; those go to the primary or fail.
- Shed instead of queueing. If the must-be-fresh class alone exceeds the primary's headroom, refuse its lowest-value slice with 503 and a retry-after. A request queued behind a saturated primary holds a connection for a client that has already given up, and the retry storm that follows is what turns degradation into an outage. Bound the connection pool per role so the read fallback cannot consume the write path's connections - that bulkhead is the single decision that determines whether writes survive the next ten minutes.
- Attack the cause in parallel, since it is the one thing that can be stopped. The backfill is the load generator. A backfill that reads replication lag as its throttle signal and pauses above a threshold would have made this a non-event, with batch sizes small enough that each batch's write volume is a fraction of what a replica can apply per second. That is most of the answer to what should have existed beforehand.
Follow-up
- Lag returns to normal in nine minutes. Which mitigation do you remove first, and which one stays permanently?
- A user reports their change did not save, and the write committed. Trace the path that produces that report and name the signal that would have shown it before the report arrived.
One log partition stops advancing while the others drain
Easy · poison message · head-of-line blocking · consumer lag
Search results for a subset of tenants are hours stale; the rest are current. The projection consumer reports lag of zero on 15 of 16 partitions and 400,000 on one. Its error rate is flat and its CPU is idle. outbox_event has no pending rows older than a second, so the relay has published everything it holds. Identify the mechanism, give the ordered checks, and state what you do in the first ten minutes versus what you change permanently.
Approach
- Read the lag distribution first. A slow consumer lags everywhere; zero on fifteen partitions and 400,000 on one is not throughput. Idle CPU on the stuck partition means the consumer is not advancing its offset at all, which points at one message it cannot get past rather than at a rate problem.
- Exonerate the producer before touching the consumer. No pending outbox rows older than a second means the relay published, so the event exists in the log. This separates never sent from sent and never applied, which are different code paths and usually different owners.
- Read the message at the stuck offset and the handler's log lines for its event_id. A flat error rate with no progress has two explanations and you must distinguish them: the handler is throwing and the retry loop is swallowing it, or the handler is blocking on something and never returning. Idle CPU with no error lines favours the second.
- Mitigate before diagnosing further. Move the offending event to a dead-letter store and commit the offset past it. Adding consumers does nothing here, because a partition is consumed by exactly one member of the group, and the blast radius is every aggregate hashed to that partition, not only the aggregate that produced the bad event.
Follow-up
- The dead-lettered event carried aggregate_version 7 and the projection had applied 6. What must the replay do differently if 8 and 9 landed in the meantime?
- How do you show staleness to the user while the partition is behind, given the API already returns the projection's watermark?
Suggested practice checklist
Seven days built from the three reported rounds and the reported questions: coding practice and JavaScript first, then the two data problems, written and presented solutions, motivation and history, and a full mock.
Day 1 — Map the loop and the requirements
- Write out the three reported stages (Application Review, Remote Interactions, On-site Assessment) and next to each the formats candidates report: remote discussion, group exercises, written test, presentation.
- List the requirements candidates describe (JavaScript, cloud environments, lifecycle practice, e-commerce, agile) and match each to one project from your own history, marking the gaps.
Deliverable: A one-page map of the three stages and a requirement-to-project table with gaps marked.
Day 2 — Good coding practice and your JavaScript approach
- Write your own definition of good coding practice as a short list, each point with a concrete habit: naming, small functions, tests, review, handling errors.
- Take a messy JavaScript function you have written or found and refactor it, noting the before and after for each of your list points.
- Prepare a spoken answer on your JavaScript approach covering modules, asynchronous code, error handling and testing, and say it aloud once.
Deliverable: A checklist of your coding practices, one before-and-after JavaScript refactor, and a written outline of the spoken answer.
Day 3 — Design: persisting a shopping basket
- Sketch the guest basket and the signed-in basket and the merge between them when the shopper logs in.
- Define the stored data per line (item, quantity, added time), when price is read, and the expiry rule for abandoned baskets.
- List three failure cases (two tabs editing the same basket, an item going out of stock, the store being unavailable) and write what the shopper sees in each.
Deliverable: A one-page basket design with a data model, the login merge flow and a failure-case table.
Day 4 — Stock transfers between locations
- Write the transfer as a single atomic change: reduce the source, increase the destination, reject a move that would leave negative stock, and record it in a movement log.
- Add an in-transit state and an idempotency key so a retried request does not apply twice.
Deliverable: A written transfer procedure with its data model, a worked retry case and a solved concurrent-edit practice question.
Day 5 — Written code and a solution built to a brief
- Write by hand, without an editor, two small JavaScript functions (a basket total with quantity limits and a stock move check) and trace each with a normal case and an edge case.
- Take a one-paragraph brief you invent about syncing stock between locations and outline a presentation in a fixed structure: constraints, design, rejected alternative, risks, business impact.
Deliverable: Two handwritten functions with traces, a one-page presentation outline, and the replication-lag practice answer.
Day 6 — Motivation, culture and career history
- Write the answer on why you want to join this retailer specifically, with at least two points that could not be said about another employer.
- Write a separate answer on culture and business model, using your own experience as the evidence, and check it does not repeat the first.
- Prepare your employment history in order, each role with scope, decision, result and lesson, and rehearse it aloud; add a group-exercise role you can play.
Deliverable: Three written answers (why this company, culture and business model, career history) and a short note of your group-exercise approach.
Day 7 — Full dry run
- Run a mock in the reported order: walk through your CV, answer the coding practice and JavaScript questions, then talk through basket persistence and stock transfers.
- Finish with a presentation of a solution to a new brief and a spoken version of your motivation answer, then write down the two questions you most want to ask the team.
Deliverable: A completed mock with notes on weak spots and two questions to ask the team.
Motivation and career history
The behavioral questions candidates report are about motivation and background: why this company, what attracts you to its business model and culture, and what you learned across your previous roles. For a Software Engineer, the strongest answers use concrete work from your own history and connect it to the retail and e-commerce engineering described for the role.
- Why do you want to join Bravissimo Ltd specifically?
- Tell me about a time you explained a technical decision to someone outside engineering. What did you leave out, and how did you check they understood?
- Describe a time you worked in a group where the task was unclear. What did you do to move it forward, and what did you do for the group?
What draws you to our company culture and business model?
Medium · Behavioral and Role Motivation
Approach
- Treat it as a question about the business model, so show you understand it first. Describe in your own words how an online retail operation depends on its software, using what you have read about the products and the website journey, and what you could not tell from outside.
- Link the model to the engineering problems that follow from it: baskets that must survive between visits, stock figures that must be right across locations, and data that must flow between systems. This shows you can connect the work to the business, which is the advice candidates relay.
- For culture, avoid claiming facts you have not verified. Speak from what you have seen (reported collaborative development, group exercises, an office tour) and from what you want in a team: shared code review, working with non-technical colleagues, steady delivery.
- Give one example from your own past that proves the preference: a team habit that worked well for you, with a result. Do not rely on adjectives like 'friendly' or 'innovative'.
- The mistake that sinks this answer is flattery that could apply to any company. Test every sentence: if you could say it about another retailer unchanged, replace it with something specific.
Follow-up
- What would worry you about working here, or what would you want to find out in your first month?
- Which part of the website journey, from browsing to checkout, would you most like to improve, and why?
- How does this team differ from the one you work in now, and what would you carry across?
Can you walk us through your employment history and the key lessons learned in previous roles?
Medium · Behavioral and Role Motivation
Approach
- Choose a spine and keep to it: either oldest role first or most recent role first. For each job give four things in order: scope in one sentence, one decision you owned, the result, and the lesson you took from it.
- Pick two or three lessons that build towards this role and say how each changed your behaviour, for example how a production incident led you to add tests around a data update, or how working with a non-technical stakeholder changed how you explain choices.
- Where your jobs relate to the requirements (JavaScript, cloud environments, lifecycle practice, e-commerce or retail, agile teamwork), name that overlap briefly and with a concrete project, not a list of technologies.
- Explain moves and gaps honestly and without blame: what you were looking for, what you learned, what you chose next. Keep it short and let the conclusion lead into why you want this role.
- The usual failure is reading the CV aloud with no lessons. Another is spending most of the time on the earliest job. Rehearse so the recent roles get the most time and each lesson has evidence behind it.
Follow-up
- Which of those lessons has most changed how you write or review code?
- Why did you leave your last role, and what did you want from the next one?
- Tell me about a decision in one of those roles that you would now make differently.
Tell callers you do not own that their integration breaks
Medium · deprecation · compatibility · stakeholders
A field in a write endpoint's response must change shape. You own the endpoint; you do not own the four internal callers or the outbound webhook consumers who read it. Describe a deprecation you were responsible for: what you shipped first, how you established who was actually reading the field, the window you gave and what set its length, what you did about the consumer who never moved, and how you decided removal was safe. Name the signal you used, not the announcement you sent.
Approach
- Establish the reader set empirically rather than from a wiki of owners: per-field usage counters keyed by principal, or access logs attributed to a consumer. State the blind spot of whichever you pick, since a consumer that reads the field only on a monthly job will not appear in a week of logs.
- Ship additive first. Populate the new field alongside the old one so no reader is forced to move, which is also what keeps a rolling deploy safe, because old and new instances answer the same requests at the same time and a rollback must still find the old shape present.
- Set the window from the slowest legitimate consumer's release cadence, not from your calendar, and decide separately what to do for a consumer with no release process at all, such as an external webhook endpoint you can only email.
- Convert silence into evidence before you rely on it: a short, low-traffic removal window that makes a still-dependent consumer fail visibly and loudly while you are watching, rather than at three in the morning after you have moved on.
Follow-up
- How would you detect a consumer that reads the field only during a monthly export?
- One caller refuses to move and has a commercial relationship behind it. What changes in your plan and what does not?