Artifax · Software Engineer
Updated · 2026-10-02

Artifax Software Engineer
Interview Guide

THE 60-SECOND BRIEF

Artifax builds software for managing venues and events, used by museums, festivals and performing arts centres. The Software Engineer role described by candidates sits on a mature PHP-based enterprise platform and has two threads: modernizing that platform and adding AI-enabled workflows to the product. Candidates describe the stack as PHP 8.2 or later with Laravel or CodeIgniter, TypeScript and React on the front end, AWS for deployment, and Docker and Kubernetes for orchestration, with RAG pipelines and vector databases listed as a bonus. The role is reported as remote-first, working with a Product Owner and the Head of Engineering, and owning a feature from design through deployment and monitoring.

This guide is for experienced engineers preparing for the Artifax Software Engineer loop. The requirements candidates describe include seven or more years of production experience, UK residency with the right to work (no visa sponsorship), and a cover letter with the application. The guide covers the six reported questions: refactoring a legacy PHP/Laravel codebase, a modernization story from your own career, REST API performance, database migrations in a long-lived application, AI tools in your daily workflow, and designing a secure AI-powered workflow. Candidates report little emphasis on competitive-programming algorithms, so the plan spends its time on design judgement, maintainable code and clear explanation.

Candidates describe an initial screening, then a technical assessment, then deeper technical interviews. No round count, order of individual interviews or per-stage format is reported, so confirm the details with your recruiter.

AI-enabled product developmentLLM integrationResponsible AI / AI guardrails

33 min read

Browse Software Engineer questions

See the practice prompts

14Practice promptsAcross five skill areas

The work behind this loop is two-sided. One side is keeping a long-running PHP platform stable while it is modernized piece by piece. The other is shipping AI-enabled features on top of it. The six reported questions follow that split: four sit under technical modernization (the Laravel refactor, your own modernization story, REST API performance, database migrations) and two under AI and innovation (your own AI tool usage, and designing a secure AI-powered workflow). Only one of the six is a pure behavioral prompt, but most of the others are answered best with a real project from your history.

Candidates report that the evaluation areas are refactoring strategy, testing habits for legacy code, dependency and library upgrades, agentic workflows for review and documentation, guardrails such as output validation and prompt security, and commercial impact. For preparation, that means building answers around concrete mechanisms. For refactoring, that is characterization tests, seams and incremental rollout. For migrations, it is a safe order of schema and code changes plus a rollback path. For AI, it is validation, data handling and fallback behaviour.

Candidates also report that algorithm drills matter less here than practical system design and maintainable, production-grade code. If the technical assessment is a take-home, a README that states your design decisions and trade-offs is a reported tip. Write that README habit into every practice exercise you do this week, and prepare to share your screen to walk through code or an architecture diagram.

01

Preparation focus

editorial

Candidates describe a process that begins with an initial screening, moves to a technical assessment, and then continues into deeper technical interviews. Nothing is reported about how many interviews follow, how long each lasts or what each contains, so ask the recruiter whether the assessment is a take-home or live, whether you will write code during the interviews, and who you will meet. Whatever the format, the six reported questions are the best map of what to prepare. Modernization, API and migration questions reward answers built on a real project, with the reason you chose each approach over its alternatives. The AI questions reward a specific toolchain and a specific safeguard rather than general enthusiasm. If the assessment produces code, add a README that states your decisions and trade-offs, since that is a reported tip.

What to demonstrate

  • Hands-on coding that is clean, documented and maintainable, which is what a technical assessment produces
  • Judgement on modernizing a PHP/Laravel codebase safely: testing, incremental change and dependency upgrades
  • Architecture reasoning for REST APIs, long-lived databases and AI-enabled workflows, including why you picked one approach over another
  • How you use AI tools in development and apply guardrails to AI features in production

How to prepare

  • Write a one-page outline of one real modernization project: starting state, hurdles, the sequence of changes, how you protected live behaviour, and the result
  • Prepare a short answer on each of the Laravel refactor, REST API performance and database migration questions, each naming a concrete mechanism rather than principles
  • Write down your actual AI toolchain (for example Copilot or Cursor if you use them), what you delegate to it, and how you verify its output before merging
  • Set up a stable screen-sharing environment and rehearse walking through code or a diagram while talking, since candidates are told to expect that
PracHub preparation framework ↗

PracHub editorial advice for the preparation topics above.

01

Answering the Laravel refactoring question with a plan to rewrite the module or the whole application

Describe an incremental path: pin current behaviour with characterization tests, introduce a seam, move one slice at a time behind a feature flag, and keep the old path until the new one has run in production. State what you would leave alone and why.

02

Telling a modernization story as a list of technologies (framework upgrade, containers, new library) with no obstacles, no decision of yours and no result

Structure it around the hurdles: what blocked you, the options you weighed, why you picked one, how you limited the risk, and what you measured afterwards. Keep it to what you personally decided.

03

Treating the database migration question as a list of schema commands, with no ordering between deploys, no handling of large tables and no rollback

Talk through the expand, backfill and contract sequence so old and new application code both work at every step. Cover how you backfill in batches without long locks, how you verify the data, and how you reverse each step if it fails.

04

Answering the AI questions with "I use Copilot or Cursor to go faster", or designing an AI workflow with only the happy path

Name what you delegate to an AI tool and what you check by hand, such as tests, review and secrets handling. For the enterprise workflow, cover input and output validation, customer data boundaries, authentication, logging, retries and a fallback when the model fails or is unavailable.

05

Submitting a technical assessment with working code but no README, or leaving out the cover letter the application requires

Include a README that states your design decisions and the trade-offs you made, as candidates are advised. Write the cover letter around a legacy system you modernized, since that is the experience the role asks for.

Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.

11 technical prompts0 include a worked solution

Merge partitioned event streams into one ordered feed with bounded lateness

hard
k-way mergewatermarksout-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?

Identify the heaviest tenants in a five-minute window under memory pressure

medium
top-kheavy hittersstreaming

The edge service handles about 3,000 requests per second across roughly 50,000 tenants, peaking near 9,000. Expose the 50 heaviest tenants by request count over the trailing five minutes so limits can be tightened before one tenant's backfill starves the fleet. You may not retain five minutes of raw records. Give the exact solution and its memory, then the bounded-memory approximation with its error stated as a formula, and say which you would ship and at what tenant cardinality that choice changes.

Approach
  1. Do the exact version first, because it is affordable at this cardinality: a ring of 300 one-second counters per tenant, advanced lazily, is 1,200 bytes of counters per tenant and roughly 60 to 90 MB for 50,000 tenants with overhead. Carry a running total and subtract the bucket you overwrite so a window read is O(1) rather than 300 adds.
  2. Extract the top 50 with a size-k min-heap over the tenant sums: O(d log k) for d tenants, against O(d log d) to sort them all. Maintaining the heap continuously instead of on query requires a tenant-to-heap-index map, because incrementing a count already inside the heap means sifting from a known position, and without that map you rebuild the heap on every request.
  3. State the approximation precisely rather than gesturing at sketches. Misra-Gries with m counters retains every item whose true count exceeds N/(m+1), and each retained count underestimates the truth by at most N/(m+1). With m = 1,000 and N = 900,000 requests in the window the error is roughly 900 requests, which is fine for spotting a tenant sending 50,000 and useless for ranking two tenants 200 apart.
  4. Say what breaks when the window slides: Misra-Gries and Space-Saving are insert-only and cannot be decremented as records age out. The workable construction is one summary per sub-window, say ten seconds, with 30 summaries merged at query time, and the merged error is the sum of the per-summary errors, so the bound degrades linearly in the number of sub-windows.
Follow-up
  • The heaviest tenant is heavy because of one export job rather than user traffic. Should the limiter treat those as the same tenant?
  • Two tenants sit tied at the boundary of the top 50. Does your answer flap, and does the flapping matter?

Archive a resource graph without breaking live references or recursing

medium
graph traversaltopological ordertenant 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?

The plan follows the six reported questions in order: the modernization story first, then the PHP/Laravel refactor, the API and database questions, the two AI questions, a take-home-style build, and a final mock. Practice-library drills support the migration, API latency and behavioral days.

Small steps. Visible outcomes.0 / 7 completed
ONE WEEK · YOUR PACE

Prepare, practise & reflect

One practical outcome each day. Spend longer where you need it.

0 / 7 done
01Confirm the format and choose your modernization story
  • Email the recruiter to ask whether the technical assessment is a take-home or live, whether you will write code in later interviews, and which stages follow the screening
  • List three systems you have modernized or refactored and pick the one where you made the key decisions
  • Outline the chosen story: starting state, hurdles, the sequence of changes, how you protected live behaviour, and the measured result

Deliverable: A recruiter email with your format questions, plus a one-page outline of the modernization story to use for the behavioral question and the cover letter.

Practice prompt ↗
02Refactor a legacy PHP/Laravel codebase safely
  • Write out your step-by-step approach for the legacy PHP/Laravel refactoring question: characterization tests, seams, one slice at a time, feature flags, rollback
  • Take a small legacy-style PHP function from your own work or a sample and write a characterization test, then extract one dependency behind an interface
  • Note how you would handle framework and library upgrades in order (PHP version, framework version, packages) and what you test after each step

Deliverable: A written refactoring plan, one characterization test with the extracted seam, and an ordered upgrade checklist.

Practice prompt ↗
03Database migrations and REST API performance
  • Outline the migration strategy answer: expand, backfill in batches, switch reads, contract, with the rollback for each step and the check that proves the data matches
  • Work the practice drill on denormalising tenant onto revisions and backfilling it live, and the one on soft-deleted accounts blocking re-registration
  • Write the REST API performance answer by layer: query and index shape, pagination, caching, payload size, rate limits, background work for slow calls, and the metrics you would watch
  • Work the practice debugging drill on a p99 spike on one listing filter, and say what you would check first

Deliverable: A migration runbook for one large-table change, a layered API performance checklist, and a written diagnosis sequence for the p99 drill.

Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗
04AI tools in your daily development lifecycle
  • Write down your actual toolchain and the tasks you hand to it: code review, documentation, prototyping, test generation
  • For each task, write the check you apply before trusting the output, such as running the tests, reading the diff or restricting what data you paste in
  • Pick one example where an AI tool improved velocity or quality and one where it was wrong, and write both as short stories with the lesson you took

Deliverable: A one-page AI workflow statement with a task-and-check table and two short stories, one success and one failure.

Practice prompt ↗
05Design a secure, reliable AI-powered workflow
  • Choose an enterprise scenario (for example summarising or classifying customer records inside a platform) and sketch the components: input validation, a retrieval step if you use RAG, the model call, output validation, storage and audit logging
  • Write the failure plan: model timeouts, malformed output, prompt injection through user content, and what the user sees when the AI step fails
  • Add the data-boundary decisions: what customer data is sent to the model, how tenants are separated, and how you would measure whether the feature delivers commercial value

Deliverable: An architecture diagram with a written failure-mode table and a list of the guardrails you would ship first.

Practice prompt ↗
06Take-home-style build with a README
  • Build a small PHP/Laravel or TypeScript/React exercise of your choice, with unit tests and one integration test
  • Write a README that states your design decisions, the alternatives you rejected and what you would do next with more time
  • Practise sharing your screen and walking through the code and the README out loud

Deliverable: A small tested project with a README of decisions and trade-offs, plus a recorded or rehearsed walkthrough.

Practice prompt ↗Practice prompt ↗
07Full mock and behavioral polish
  • Answer all six reported questions out loud in sequence, using your outlines from days 1 to 5
  • Work the practice behavioral drills on shipping under a deadline while bounding the debt, and on unblocking an engineer without taking the keyboard
  • Finalise the cover letter around the modernization story, and write two questions to ask the team about the platform and the AI roadmap

Deliverable: A spoken run of all six answers, notes on where you hesitated, a finished cover letter and two questions for the team.

Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗

Expand any day for tasks and deliverables. Your progress is saved on this device.

The behavioral material reported for this role centres on one prompt, a time you modernized a complex system, and the surrounding themes of ownership, trade-offs between delivery speed and maintainability, and responsible use of AI. Prepare stories where you made the decision and can say why you chose it over the alternatives.

Describe a time you had to modernize a complex system. What were the biggest technical hurdles?

medium
Technical & Modernization

Describe a time you had to modernize a complex system. What were the biggest technical hurdles?

Approach
  1. Choose a project where you made the key decision, and where the system was a real production system with users depending on it. A story where you carried out someone else's plan, or a greenfield rewrite nobody relied on, gives you nothing to defend. If you can, pick one involving a PHP or other long-lived web application, since that matches the platform described for this role.
  2. Open with two sentences of context: what the system did, why it needed modernizing, and what constraint (live customers, no test suite, a deadline) shaped the approach. Then spend most of your time on the hurdles. Name them specifically: undocumented business rules, tight coupling between modules, missing tests, an outdated framework or library version, or a data migration that could not take downtime.
  3. For each hurdle, say what you did and why you chose it over the alternative. A typical sequence is to write characterization tests that pin current behaviour, introduce a seam around one area, move that area behind the new code, run old and new side by side or behind a feature flag, then cut over and delete the old path. State the reason you avoided a big-bang rewrite.
  4. Give the blast radius and the evidence. Say what could have broken, how you limited exposure (staged rollout, rollback plan, monitoring on the affected paths), and what you measured afterwards, such as error rates, latency, deploy frequency or test coverage on the touched code. Use only figures you can actually stand behind.
  5. The mistake that sinks this answer is a technology list with no obstacles ("we moved to the newer framework version and it went well"). Include one disagreement or trade-off, say how you settled it with evidence, and close with what you would change if you ran the project again.
Follow-up
  • What was the single hardest hurdle, and what would have happened if your first approach to it had failed?
  • How did you decide what to leave in the old system rather than modernize?
  • How did you show that your change, and not something else, improved the outcome?

Ship under a deadline and bound the debt you chose

medium
paginationtechnical debttradeoffs

You have four days to ship a tenant-facing listing endpoint. The version you would defend uses keyset pagination over (tenant_id, status, updated_at DESC, resource_id DESC); the version you can finish uses LIMIT/OFFSET with no matching index. Describe a deadline call you actually made of this shape: what you shipped, what you knowingly deferred, how you bounded the damage with a mechanism rather than an intention, and the specific numeric condition that would force the follow-up. Name who you told and where you wrote it down.

Approach
  1. Name the deferred failure precisely instead of calling it slow. OFFSET n makes the database produce and discard n rows, so cost grows with page depth; without an index matching the sort, every matching row is read and sorted before the limit applies; and rows inserted between two page fetches shift across the boundary so items are skipped or repeated with nothing in the response to signal it.
  2. Bound the blast radius with something mechanical rather than a promise: cap maximum page depth, cap page size, restrict the endpoint to one internal caller, or keep it behind a flag. State which failure each cap removes and which it leaves standing.
  3. Attach a number to the trigger and wire it to an alarm: the first tenant crossing N resources, or the endpoint's p99 crossing its share of the 400 ms budget, so the debt announces itself instead of waiting to be remembered.
  4. Write it where the next engineer looks, which is the code and the ticket, not a chat message: what was deferred, why, the cap, and the trigger.
Follow-up
  • At what page depth does the offset version breach your latency budget, given your page size and row counts?
  • What breaks first when you switch to keyset pagination later, and what does a client holding an old page token see?

Unblock an engineer without taking the keyboard

easy
mentoringleasesat-least-once

A teammate has spent two days on a job handler that occasionally writes duplicate rows. They are certain the queue is delivering twice by mistake. You suspect a lease expiring under a slow handler, so the job is running concurrently with itself. Describe how you have unblocked someone in this position: what you asked before offering a hypothesis, what you showed them rather than told them, and what you left them owning. Then say what you would do if their theory turned out to be the right one.

Approach
  1. Ask before diagnosing, and ask for things answerable from data they already have: the attempt count on the job rows that produced duplicates, the handler's observed duration against its lease expiry, and whether the duplicate rows share a natural key that a unique constraint could have caught.
  2. Teach the shape rather than the answer. A lease cannot distinguish a dead worker from a slow one, so a handler that outruns its lease is running twice by design, and deploys deliver the other half by killing handlers mid-run on every rollout. Both of their candidate theories produce identical duplicate rows, which is why the evidence has to come from timings rather than from argument.
  3. Hand over a checklist they execute: a natural key on every write the handler performs so the second copy collides rather than appends, the record of intent written before any external effect, a lease heartbeat while running, and the metric that shows it working.
  4. Keep ownership with them deliberately. Pair on the first write, then step back; if you finish it yourself you have closed one ticket and left the same person stuck on the next redelivery.
Follow-up
  • How would you distinguish a genuine double-delivery from a lease expiry using only the data already stored?
  • Their handler calls an external endpoint before recording that it did. What do you tell them to change first?
  • 01

    Describe a time you had to modernize a complex system. What were the biggest technical hurdles?

  • 02

    Tell me about a time you balanced delivery speed against long-term maintainability, and what you chose to leave alone.

  • 03

    Describe a time an AI tool gave you something wrong or unsafe. How did you catch it, and what did you change afterwards?

  • 04

    Tell me about a feature you owned from design through deployment and monitoring. What did you check after release?

  • 05

    Describe a time you worked with a product owner to turn a vague request into a technical specification.

PracHub preparation framework ↗
How should I approach the technical task?

Candidates describe a technical assessment after the initial screening, and the advice they report is to treat the code as a statement of your professional standards: clean, documented and following good practice. Include a README that explains your design decisions and trade-offs. Ask the recruiter whether it is a take-home or live, and what you may use.

Artifax Software Engineer candidate reports ↗
Is there a specific focus on algorithms?

Candidates report less emphasis on competitive-programming puzzles and more on practical system design and maintainable, production-grade code. The six reported questions are about refactoring, API performance, database migrations and AI workflows, so spend your time there rather than on algorithm drills.

Artifax Software Engineer candidate reports ↗
What topics does Artifax test in interviews?

Candidates report AI-enabled product development, LLM integration, responsible AI and guardrails, software architecture and engineering judgement, and legacy systems modernization. Evaluation areas include refactoring strategy, testing habits for legacy code, dependency management, agentic workflows, reliability guardrails and commercial impact.

Artifax Software Engineer candidate reports ↗
Which technologies should I review?

The requirements candidates describe list PHP 8.2 or later with Laravel or CodeIgniter, TypeScript and React, AWS and containerization, with Docker and Kubernetes mentioned for deployments. RAG pipelines and vector databases are listed as nice to have. Review how you would test and incrementally upgrade a Laravel application, and be ready to explain a deployment you owned.

PracHub Software Engineer practice ↗
What are the application requirements?

Candidates report that the role asks for seven or more years of production experience, UK residency with the right to work, and no visa sponsorship. They also report that a cover letter is required and that applications without one are not considered. A reported tip is to use the letter to describe a time you successfully modernized a legacy system.

PracHub Software Engineer practice ↗
How do I answer the questions about using AI tools?

Be specific. Name the tools you use, the tasks you give them (review, documentation, prototyping, test scaffolding) and the check you apply before trusting the result. Pair that with one example where it saved effort and one where it was wrong. For production AI features, talk about validating output, protecting customer data and handling failure.

PracHub Software Engineer practice ↗
Sources & methodology 3 sources ↗

No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.