Choose one role before choosing a practice project. A general product-engineering conversation can center on a creator feed or a reliable publish flow. A Growth conversation needs an additional measurement contract: who entered the experiment, what counted as activation and what could get worse while the main metric improved. The examples below let you reuse a small feature across those discussions without pretending the two roles have identical expectations.
Build the smallest slice that exposes a real boundary. A feed needs a stable order, controlled fetching and a response that belongs to the current viewer. A publishing workflow needs to distinguish an uploaded file from an approved, visible post. Write those conditions down before implementing the happy path. They give you concrete things to test and help a reviewer follow the reason for each branch in the code.
Use Python and SQLite here as compact reference tools, then transfer one exercise into the TypeScript stack attached to your opening. Keep the assertions and the API contract the same during that transfer. Work with synthetic creator IDs and sample media metadata; no real accounts or platform writes are needed for this preparation. Bring the test and a short explanation of the tradeoff, not a large application that is difficult to review.
Connect your experience to creator workflows
editorialPrepare an opening explanation around one user journey: a creator publishing a post, a fan finding it, or an agency managing an authorized account. Use that journey to show which engineering decisions you owned. Keep a concrete request flow available so the discussion can move from product intent to implementation without losing the user’s goal.
What to demonstrate
- Separate creator, fan and agency identities when describing access. Explain one boundary where confusing those identities would return the wrong data.
- Connect a change to an observable outcome, such as a successful publish action or a completed onboarding step, without substituting a vanity metric.
How to prepare
- Choose one feature from your own work and sketch browser, API, storage and async work. Label who can read or change the resulting state.
- Prepare a short before-and-after example with one test or operational observation. Be precise about what you built personally and what a teammate or external service supplied.
Build a complete, bounded product slice
editorialUse a small creator feed as a practice project. The useful result is a working vertical slice with a clear request contract, loading and error states, and a repeatable test. Keep the scope narrow enough that another engineer can inspect the behavior in a few minutes. A polished grid that silently drops records is weaker evidence than a plain list with correct pagination.
What to demonstrate
- Demonstrate stable ordering across tied timestamps, and explain how authorization constrains the feed before paging begins.
- Make asynchronous behavior visible: limit expensive work, prevent stale responses and distinguish an empty result from a failed request.
How to prepare
- Implement the cursor exercise, then translate its contract into TypeScript and a small API boundary. Test a tie, an empty page and an invalid limit.
- Add a controllable delay to two requests and reverse their completion order. Keep one screenshot or trace of the failure and the regression check that demonstrates the fix.
Explain access and publication state
editorialPractise moving from a successful request to the failures around it. For a subscription product, media processing, permission checks and publication visibility are different responsibilities. Explain where each decision is made and which state remains durable after a restart. Use your own small model to make the boundaries explicit instead of asserting knowledge of the employer’s internal systems.
What to demonstrate
- Protect the distinction between owning a post, being allowed to manage its creator and being entitled to view private content.
- Describe what repeated commands and late worker results do to the current media version, including a publication request that times out after committing.
How to prepare
- Draw the upload workflow with states and guard conditions. Inject a replaced file followed by an approval for the old version and show why it stays hidden.
- Write a short cache-key review: list every identity and permission input that affects the response, then construct a case where a key that is too broad returns another account’s data.
Own the behavior of AI-assisted changes
editorialThe engineering posting includes AI-assisted development and AI product work. For preparation, choose a contained change and retain the evidence behind the result: the input, the important diff and a test you checked yourself. Be ready to explain a suggestion you changed or rejected. Tool fluency is useful only when you can account for the behavior shipped to users.
What to demonstrate
- Explain the relevant implementation without outsourcing the reasoning to an assistant’s summary or a generated test that repeats the same assumption.
- Keep generated content separate from user permissions and publication decisions. A model’s output is an input to application logic, not authority to perform a privileged operation.
How to prepare
- Ask a tool to help with a small feed or workflow change, then deliberately review the error path and authorization boundary yourself.
- Save a compact record of a mistaken suggestion, your correction and the independent check. Practise explaining it as an engineering judgment rather than a list of prompts you entered.
Review a product result and decide what happens next
editorialPrepare a final walkthrough that joins correctness and product judgment. A creator can complete more onboarding steps while encountering a worse publishing experience, so one improving number is not enough. For the Growth track, use a simple experiment readout; for another engineering track, use an equivalent feature outcome and a regression guardrail. Keep the decision grounded in the actual observation window.
What to demonstrate
- Keep exposure, activation and repeated events distinct. Explain who is in the denominator and which users have had enough time to complete the measured action.
- Discuss an unfavorable result openly and name the next action: stop, revise or collect a specific missing observation.
How to prepare
- Run the activation SQL fixture and add the boundary cases before calculating a percentage. Rehearse explaining why duplicate events do not imply extra activated creators.
- Prepare a real example of ending an experiment or reducing its scope. Include the stakeholder conversation, the evidence you trusted and the follow-up that made the decision stick.
PracHub editorial advice for the preparation topics above.
Showing a polished feed without a correctness contract
Start with ordering, identity and access. Test two posts with the same timestamp, an overlap between pages and a viewer switch while a request is running. Keep a small recorded sequence that exposes each failure. Visual polish matters after the page consistently shows the right records to the right viewer; a successful screenshot alone cannot demonstrate that behavior.
Treating a UI state or media URL as permission
Trace a read from authenticated identity to the content owner and entitlement decision. Review the cache key against those inputs. For a publishing exercise, distinguish approval of one media version from permission to reveal a later replacement. Explain both the API check and the delivery boundary, because hiding a button does not protect a direct request.
Calling extra events an activation improvement
Count creators before counting their actions. Duplicate publish events must not enlarge the numerator, and users without events must remain in the denominator. Exclude cohorts that have not completed the observation window, then show the sample size and a relevant guardrail. Keep the measurement assumptions next to the result so another engineer can challenge the conclusion.
Presenting generated code without independent evidence
Choose one important behavior and verify it outside the tool’s explanation. Force the stale-response order, check the SQL boundary or inspect which identity enters the access decision. Keep the diff small enough that you can explain the relevant branch. If an assistant supplied a convincing but incorrect test, describe how a separate counterexample exposed its assumption.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Page a creator feed without dropping tied timestamps
Implement page(posts, after, limit) for an authorized, fixed feed snapshot. Each post has a unique integer id and integer created_at. Sort descending by (created_at, id), and return posts strictly older than an optional cursor tuple. Reject limit <= 0. Return a next cursor only if more posts remain.
Approach
- Use the ID as a deterministic tie-breaker. Comparing only timestamps loses posts created at the same instant.
- Filter against the complete cursor tuple before taking a page. Fetch or retain one extra row to decide whether another page exists.
- Keep authorization and snapshot semantics explicit. The cursor orders a result set; it does not grant access to a creator.
Worked solution 35 min
- The test has three posts at timestamp 10. Descending IDs give a complete order, so page two can still retrieve id 1.
- This in-memory reference sorts in O(n log n) and uses O(n) space. A database implementation should use a compound index and a page-size-plus-one query.
- The function assumes unique IDs and validated integer timestamps in one authorized snapshot. It is not a Fanvue API implementation.
def page(posts, after=None, limit=2):
if limit <= 0:
raise ValueError("limit must be positive")
key = lambda post: (post["created_at"], post["id"])
ordered = sorted(posts, key=key, reverse=True)
eligible = [p for p in ordered if after is None or key(p) < after]
selected = eligible[:limit]
cursor = key(selected[-1]) if len(eligible) > limit else None
return [dict(p) for p in selected], cursor
posts = [dict(id=1, created_at=10), dict(id=3, created_at=10),
dict(id=2, created_at=10), dict(id=4, created_at=9)]
first, cursor = page(posts)
second, end = page(posts, cursor)
assert [p["id"] for p in first] == [3, 2]
assert [p["id"] for p in second] == [1, 4]
assert end is None
Scroll sideways to view long lines.
Follow-up
- How would inserts between page requests change the snapshot contract?
- What compound index supports the ordering?
- How would you sign an opaque cursor without putting credentials in it?
Merge overlapping pages into one visible feed
Given two ordered pages with overlapping post IDs, produce a combined list with one entry per ID while preserving first-seen order. If the later page supplies a changed title for an existing ID, update the title without moving the entry. Inputs are already authorized for the same viewer.
Approach
- Separate ordering from the latest display payload: keep an ordered ID list and an ID-to-post map.
- Copy retained records so a caller cannot mutate the rendered state through an input object.
- Define how deletion and visibility changes reach the client; absence from a page is not a deletion event.
Follow-up
- How do you bound memory during a long session?
- What if the viewer changes while another page is loading?
Limit concurrent thumbnail requests
Design an asynchronous mapLimit(items, limit, fetchOne) that runs at most limit thumbnail requests concurrently and preserves input order in its results. For this exercise, collect a success/error result for every item rather than stopping at the first failure.
Approach
- Assign each task an input index and write its result into that index; completion order can differ.
- Use a fixed number of workers or a semaphore. Creating all network promises before acquiring a permit defeats the limit.
- Define cancellation separately from an individual failed fetch; stop scheduling new work when the screen closes.
Follow-up
- How do retries interact with your concurrency budget?
- What would you measure before increasing the limit?
Measure creator activation without changing the denominator
Given exposures(creator_id, variant, exposed_at) with one row per creator, and events(creator_id, kind, happened_at), count exposed and activated creators by variant. A creator activates if at least one publish event occurs in [exposed_at, exposed_at + 86400). Timestamps are integer seconds. Include variants with zero activations.
Approach
- Start from exposures so a creator with no events stays in the denominator.
- Use EXISTS or aggregate to one row per creator before grouping; repeated publish events must not count a creator twice.
- Exclude pre-exposure events and the exact upper time boundary. Report numerator and denominator together.
Worked solution 30 min
- Run the complete SQL fixture in SQLite. Creator a has two eligible publish events but activates only once.
- Creator b publishes exactly at the excluded 24-hour boundary; c publishes before exposure. Both remain in the denominator.
- Use only fully observed cohorts for a real comparison. This example verifies counting logic, not statistical significance or Fanvue experiment outcomes.
WITH exposures(creator_id, variant, exposed_at) AS (
VALUES ('a','A',100), ('b','A',100), ('c','B',100)
), events(creator_id, kind, happened_at) AS (
VALUES ('a','publish',100), ('a','publish',101),
('b','publish',86500), ('c','publish',99)
), per_creator AS (
SELECT x.creator_id, x.variant,
EXISTS (
SELECT 1 FROM events e
WHERE e.creator_id = x.creator_id
AND e.kind = 'publish'
AND e.happened_at >= x.exposed_at
AND e.happened_at < x.exposed_at + 86400
) AS activated
FROM exposures x
)
SELECT variant, COUNT(*) AS exposed, SUM(activated) AS activated
FROM per_creator
GROUP BY variant
ORDER BY variant;
Scroll sideways to view long lines.
Follow-up
- How would incomplete 24-hour observation windows bias the result?
- Which assignment and exclusion rules belong in the experiment contract?
Reconcile purchases and partial refunds in integer cents
Given purchases(id, creator_id, amount_cents) and refunds(id, purchase_id, amount_cents), report net cents per creator. Refund IDs are unique, multiple partial refunds can reference one purchase, and over-refunds are invalid input. Creators without refunds must retain their gross purchases.
Approach
- Aggregate refunds by purchase first; joining raw refund rows would repeat the purchase amount.
- Left-join the aggregate and use zero for an absent refund sum.
- Keep currencies separate and use integers. State the data-quality check that flags total refunds above a purchase.
Follow-up
- How do you handle a refund arriving before its purchase import?
- What if the report is limited by transaction time rather than purchase time?
Design a creator upload-to-publication workflow
Design a practice service where a creator uploads media, checks its preview and requests publication. Processing and moderation can fail or finish late. Define durable states, retry behavior and the conditions under which an authorized fan can see the item. These are exercise requirements, not Fanvue architecture claims.
Which media-processing result may become current?
Choose a scenario to trace what changes.
The current worker finishes processing the current upload.
- 01Claim the media versionBind work to the creator, post, upload version and current worker token.
- 02Process the fileStore the output separately until its identity and ownership checks pass.
- 03Commit the current resultRecord processing success conditionally; leave the item hidden pending review.
Commit the processing result; publication still needs the current version to pass review and an authorized publish request.
PracHub media-worker model. A processing result is eligible only for the current upload version and ownership token. Passing processing alone does not grant publication or fan access.
Approach
- Separate receiving an upload from making a post visible. Persist the owner, media version and workflow state.
- Tie processing and moderation results to the exact version reviewed. A late approval for an older file cannot release a replacement.
- Make publication a guarded state transition, and recheck access when delivering private media.
Worked solution 50 min
- Create a durable post record scoped to its creator. Record a media version and an idempotency key for each upload request.
- Use UPLOADING → PROCESSING → REVIEW_PENDING → READY → PUBLISHED. FAILED and REJECTED remain visible to the owner with actionable status, but never appear in fan feeds.
- Workers persist results for (post_id, media_version). A newer upload invalidates earlier processing and review results; late messages are ignored or retained as history.
- The publish command checks ownership, the current media version and READY state in a transaction. Store an outbox event with that transition; retries return the existing outcome.
- Feed and media delivery both enforce visibility and entitlement. A CDN URL or a UI badge alone is insufficient authorization for private content.
- Test restart after state commit, duplicate delivery, a replaced file with an old approval and a withdrawn item already cached in a feed. Show which component reconciles each state.
Follow-up
- How does an appeal change visibility?
- How do you reconcile a timed-out publish request?
- Where can operators inspect a stuck job?
Keep subscription access correct through cache changes
Design a paid-content access check for a subscription service. Account identity, creator ownership and entitlement expiry are separate inputs. Describe how cache hits, expired subscriptions and unavailable entitlement storage affect the response.
Approach
- Authorize on the server using an authenticated viewer and the requested creator/content owner.
- Include the relevant identity and entitlement version in cache boundaries. A cached media location must not become a reusable permission grant.
- Choose and explain a failure policy for new access checks when authoritative state is unavailable; expose the decision in operational metrics.
Follow-up
- What changes when the caller manages several creator accounts?
- How would you test revocation while a page is open?
Stop an old creator request from replacing the current screen
A page starts loading creator A, then the viewer switches to creator B. B finishes first; A finishes later and overwrites B. Build a small request-generation model that accepts results only from the newest request, even when two consecutive requests target the same creator.
Approach
- Reproduce both response orders and the same-creator refresh case. Comparing creator IDs alone is insufficient.
- Increment a generation when beginning each load and compare it when committing the result.
- Clear or deliberately mark old data when the context changes. Abort old work to save resources, while retaining the generation check for correctness.
Worked solution 30 min
- The incorrect implementation assigns items whenever a request finishes. Start A, start B, finish B, then finish A to expose the overwrite.
- The reference below assigns a generation at request start and allows only that generation to commit. The same-creator refresh case uses the same rule.
- Treat cancellation as a resource optimization. The generation guard still decides correctness if a cancelled request produces a late callback. In React, also guard unmount and error completion.
class FeedState:
def __init__(self):
self.generation = 0
self.creator = None
self.items = []
def begin(self, creator):
self.generation += 1
self.creator = creator
self.items = []
return self.generation
def commit(self, generation, items):
if generation != self.generation:
return False
self.items = list(items)
return True
state = FeedState()
old = state.begin("A")
new = state.begin("B")
assert state.commit(new, ["B post"])
assert not state.commit(old, ["A post"])
assert state.creator == "B" and state.items == ["B post"]
Scroll sideways to view long lines.
Follow-up
- What happens if the latest request fails?
- How would you bind this model to React effects without retaining state after unmount?
A PracHub practice schedule: complete one pair of related tasks per session and keep the result you can explain or run. Adjust the pace to your experience; this is not an employer hiring timeline.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Map the creator journey
- Sketch a creator action and its fan-facing result.
- Write examples with equal timestamps and changing page sizes.
Deliverable: A role-focused request and permission map; A cursor contract
Practice prompt ↗02Implement and test paging
- Run empty, tied and invalid-limit cases.
- Merge a repeated post without moving its position.
Deliverable: A tested reference solution; A state update with identity tests
Practice prompt ↗Worked solution ↗03Bound concurrent work
- Implement workers and test mixed request failures.
- Delay two creator requests and reverse their completion.
Deliverable: A concurrency trace; A deterministic race regression
Practice prompt ↗Worked solution ↗04Review one complete product slice
- Walk through the feed with loading, error and empty states.
- Run the SQL fixture and explain its denominator.
Deliverable: A concise end-to-end demo; A query and boundary-case table
Worked solution ↗05Reconcile partial refunds
- Aggregate before joining and preserve no-refund purchases.
- Draw states and reject a stale media approval.
Deliverable: A cents-based result with checks; A workflow and failure table
Practice prompt ↗Worked solution ↗06Review subscription access
- Challenge cache keys and expiry handling.
- Explain a corrected tool suggestion using independent evidence.
Deliverable: An authorization and cache review; A short technical ownership story
Practice prompt ↗Practice prompt ↗07Present an experiment decision
- Combine a product result with a correctness guardrail.
- Review your exact invitation, explain the demo, then repair its weakest point.
Deliverable: A five-minute evidence-based readout; A focused interview-day walkthrough
Practice prompt ↗Practice prompt ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Use real examples about experiment decisions, AI-assisted code review and creator-facing reliability.
Explain why you stopped a feature you built
Describe an experiment where the result did not support shipping. Explain the initial hypothesis, assignment rule, metric, guardrail and decision you made after seeing the evidence.
Approach
- Separate a completed feature from an improved outcome.
- Give the actual numerator, denominator and observation window when available.
- Explain what you learned and what you removed or retained.
Follow-up
- Which alternative explanation did you rule out?
- How did you communicate the result to a stakeholder invested in the idea?
Show how you verified AI-assisted code
Choose a real change where an AI coding tool helped. Explain one output you rejected or corrected, the defect it could have introduced, and the evidence that made the final change safe to ship.
Approach
- Describe the task boundary and what the tool could access.
- Point to a test or trace you independently checked.
- Explain your own reasoning about the important behavior without relying on the tool transcript.
Follow-up
- What would you change in the team workflow?
- How did you keep the diff reviewable?
Prioritize a creator-facing incident under uncertainty
Describe an incident where a user-facing feature was wrong or unavailable. Explain the observable impact, the first reversible mitigation and how you kept stakeholders updated while diagnosis continued.
Approach
- Use impact to choose the first action rather than guessing the root cause.
- Name the observation that would make you reverse the mitigation.
- Close with the follow-up check that showed recovery and prevented recurrence.
Follow-up
- How did you distinguish a broad incident from one account’s configuration?
- What remained uncertain at the end?
- 01
Bring one result you improved and one decision you changed after seeing evidence.
Does the role expect AI coding tools?
The software engineering posting includes AI-assisted development. Prepare to explain how you verified the output and made the final decision. Tool use during a particular interview follows the instructions in that invitation.
Fanvue — Software Engineer role ↗How should I adapt this guide for the Growth role?
Spend more time on assignment rules, complete observation windows, funnel metrics and the decision after an experiment. Use the activation SQL exercise and a real example of stopping or changing an idea. The separate Growth posting supplies that role-specific context.
Fanvue — Senior Software Engineer, Growth ↗Why do the worked examples use Python and SQLite?
They make the ordering, async-state and counting contracts quick to execute offline. Reimplement one in TypeScript and your chosen database before the interview. These examples do not assert Fanvue’s internal implementation.
Do I need a real Fanvue account to practise?
No. Every exercise here uses synthetic data and runs offline. The public integration-testing documentation describes real controlled accounts rather than a separate API sandbox; that integration workflow is unnecessary for these interview exercises.
Fanvue — Testing your app ↗Sources & methodology 6 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01Fanvue — About ↗
Creator monetisation product context.
official · Accessed 2026-09-13 - 02Fanvue — Software Engineer role ↗
TypeScript/Node.js and AI-assisted product engineering. The posting contains mixed seniority wording; this guide does not infer a level or interview sequence.
official · Accessed 2026-09-20 - 03Fanvue — Senior Software Engineer, Growth ↗
Separate Growth track: experimentation and end-to-end product outcomes.
official · Accessed 2026-09-20 - 04Fanvue — Developer API introduction ↗
Public developer documentation for creator and agency workflows and OAuth access.
official · Accessed 2026-09-20 - 05Fanvue — Testing your app ↗
The public API uses real controlled accounts; the exercises here run entirely offline.
official · Accessed 2026-09-20 - 06PracHub — Software Engineer questions ↗
Software Engineer practice across companies.
platform · Accessed 2026-09-13