As a Software Engineer at Tessian, you will be responsible for building intelligent, data-driven security systems designed to protect organizations against advanced email threats, accidental data loss, and unauthorized data exfiltration. Tessian operates at the intersection of cybersecurity, machine learning, and cloud backend engineering. Engineers here develop real-time detection engines that analyze millions of email data points daily, requiring robust software craftsmanship, high availability, and exceptional performance. In this role, your work directly safeguards human enterprise communication. Whether you are crafting resilient backend microservices in Python, constructing responsive user interfaces in React, or designing scalable cloud infrastructure, your contributions directly impact how thousands of global enterprises secure their data. The engineering culture prioritizes clean code, thorough testing, thoughtful architecture, and clear cross-functional collaboration. Navigating engineering at Tessian means solving complex technical problems with measurable real-world consequences. Candidates are expected to bring strong computer science fundamentals, deep language proficiency, and a pragmatic approach to system design and problem-solving.
Automated Technical Assessment
reportedBegin with a HackerRank assessment focusing on data manipulation and parsing logic.
What to demonstrate
- Begin with a HackerRank assessment focusing on data manipulation and parsing logic
- Depth in Python
How to prepare
- Answer aloud and timed: Write a program to convert a Prefix (Preorder) mathematical expression into an Infix expression and evaluate its numeric result.
- Answer aloud and timed: Evaluate a Postfix (Reverse Polish Notation) mathematical expression containing variables and basic arithmetic operators.
Recruiter Screen
reportedDiscuss your background and interest in the role with a recruiter after passing the assessment.
What to demonstrate
- Discuss your background and interest in the role with a recruiter after passing the assessment
- Depth in Python
How to prepare
- Be able to walk your CV end to end in two minutes, and say why this company specifically.
- Have your salary expectations, notice period and location constraints ready, and ask for the rest of the loop in writing.
Code Pair Interview
reportedEngage in a live technical interaction solving problems alongside an engineer.
What to demonstrate
- Engage in a live technical interaction solving problems alongside an engineer
- Depth in Python
How to prepare
- Answer aloud and timed: Explain how closures and variable scope hoisting function in JavaScript, and demonstrate how they impact asynchronous execution in
setTimeout. - Answer aloud and timed: Discuss Python memory management, built-in data structure implementations, and how dictionary hashing affects lookup performance.
Virtual Onsite Loop
reportedParticipate in deep-dive technical sessions and a behavioral interview, often with senior leadership.
What to demonstrate
- Participate in deep-dive technical sessions and a behavioral interview, often with senior leadership
- Depth in Python
How to prepare
- Answer aloud and timed: Demonstrate how to optimize component rendering in React, addressing state management and re-render triggers.
- Answer aloud and timed: Discuss the browser event loop, task queues, microtasks, and local browser storage options.
PracHub editorial advice for the preparation topics above.
Going into the loop without having done this.
Talk through your thought process continuously: During pair-programming rounds, do not code in silence. State your intended approach, discuss alternatives, and explain why you chose a particular data structure before writing code.
Going into the loop without having done this.
Master basic string manipulation and parsing: Given Tessian's cybersecurity focus on email streams, brush up on string tokenization, regular expressions, and parsing logic.
Going into the loop without having done this.
Practice expression evaluation algorithms: Review stack-based algorithms for prefix, infix, and postfix conversion and evaluation, as these frequently appear in technical screens.
Going into the loop without having done this.
When discussing past experience in the behavioral rounds, use the STAR method (Situation, Task, Action, Result). Focus heavily on the technical actions YOU took and the quantifiable engineering outcomes.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Write a program to convert a Prefix (Preorder) mathematical expression into an Infix expression and evaluate i
Write a program to convert a Prefix (Preorder) mathematical expression into an Infix expression and evaluate its numeric result.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Evaluate a Postfix (Reverse Polish Notation) mathematical expression containing variables and basic arithmetic
Evaluate a Postfix (Reverse Polish Notation) mathematical expression containing variables and basic arithmetic operators.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Implement an algorithm to parse string tokens and handle mathematical operator precedence safely within fixed
Implement an algorithm to parse string tokens and handle mathematical operator precedence safely within fixed memory bounds.
Approach
- Say what the runtime actually does before reasoning about the code.
- Name what is shared across threads and what owns each piece of state.
- Identify the window where an invariant is briefly untrue.
- Distinguish a value from a reference to it, and say which one you handed out.
Follow-up
- What happens if two callers reach this at the same time?
- Where could this allocate more than you expect?
Explain the time and space complexity of your tree traversal algorithm when evaluating deeply nested mathemati
Explain the time and space complexity of your tree traversal algorithm when evaluating deeply nested mathematical expressions.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Explain how closures and variable scope hoisting function in JavaScript, and demonstrate how they impact async
Explain how closures and variable scope hoisting function in JavaScript, and demonstrate how they impact asynchronous execution in setTimeout.
Approach
- Say what the runtime actually does before reasoning about the code.
- Name what is shared across threads and what owns each piece of state.
- Identify the window where an invariant is briefly untrue.
- Distinguish a value from a reference to it, and say which one you handed out.
Follow-up
- What happens if two callers reach this at the same time?
- Where could this allocate more than you expect?
Discuss Python memory management, built-in data structure implementations, and how dictionary hashing affects
Discuss Python memory management, built-in data structure implementations, and how dictionary hashing affects lookup performance.
Approach
- Say what the runtime actually does before reasoning about the code.
- Name what is shared across threads and what owns each piece of state.
- Identify the window where an invariant is briefly untrue.
- Distinguish a value from a reference to it, and say which one you handed out.
Follow-up
- What happens if two callers reach this at the same time?
- Where could this allocate more than you expect?
Demonstrate how to optimize component rendering in React, addressing state management and re-render triggers.
Demonstrate how to optimize component rendering in React, addressing state management and re-render triggers.
Approach
- Say what the runtime actually does before reasoning about the code.
- Name what is shared across threads and what owns each piece of state.
- Identify the window where an invariant is briefly untrue.
- Distinguish a value from a reference to it, and say which one you handed out.
Follow-up
- What happens if two callers reach this at the same time?
- Where could this allocate more than you expect?
Discuss the browser event loop, task queues, microtasks, and local browser storage options.
Discuss the browser event loop, task queues, microtasks, and local browser storage options.
Approach
- Say what the runtime actually does before reasoning about the code.
- Name what is shared across threads and what owns each piece of state.
- Identify the window where an invariant is briefly untrue.
- Distinguish a value from a reference to it, and say which one you handed out.
Follow-up
- What happens if two callers reach this at the same time?
- Where could this allocate more than you expect?
Write a function to parse, clean, and analyze email header strings to detect anomalies within optimal time bou
Write a function to parse, clean, and analyze email header strings to detect anomalies within optimal time bounds.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Compare the architectural trade-offs between using hash tables, set operations, and sorted arrays for frequent
Compare the architectural trade-offs between using hash tables, set operations, and sorted arrays for frequent search queries over large string collections.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Analyze the time and space complexity trade-offs of using auxiliary data structures versus in-place string mod
Analyze the time and space complexity trade-offs of using auxiliary data structures versus in-place string modification.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Implement a string lookup mechanism that optimizes for immediate query speed at the expense of initial index c
Implement a string lookup mechanism that optimizes for immediate query speed at the expense of initial index construction time.
Approach
- Name the grain you start from and join outward from it.
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- Say which index the query would use, and what makes it unusable.
- Handle the rows that do not match: that is usually the actual question.
Follow-up
- How does the query change if that join becomes one-to-many?
- What happens to this when the table is ten times larger?
Find version gaps and relay lag with window functions
outbox_event holds event_id, aggregate_type, aggregate_id, aggregate_version, event_type, payload, status ('pending','published','dead'), attempts, created_at, published_at. A projection is missing rows and you must decide whether the relay skipped events or the consumer dropped them. Write three queries over the last seven days: one listing every aggregate_id whose published aggregate_version sequence has a hole, one giving per-day counts with a running total, and one returning the newest published event per aggregate. For each, say where the window function is evaluated relative to WHERE and LIMIT. PostgreSQL 16.
Approach
- Gaps: compute lead(aggregate_version) OVER (PARTITION BY aggregate_id ORDER BY aggregate_version) in a subquery, then filter next_version <> aggregate_version + 1 in the outer query. Window functions are evaluated after WHERE, GROUP BY and HAVING and before the outer ORDER BY and LIMIT, so the predicate cannot sit in the same WHERE clause and PostgreSQL 16 has no QUALIFY.
- Say what the seven-day filter does to the answer: it truncates every partition, so the first row per aggregate has no predecessor inside the window and a hole spanning the boundary is invisible. Widen the window, or join to resource.version as the authority for the true maximum.
- Running total: SELECT date_trunc('day', created_at) AS d, count() AS n, sum(count()) OVER (ORDER BY date_trunc('day', created_at) ROWS UNBOUNDED PRECEDING). An aggregate inside a window call is legal because grouping runs before windowing. The grouping key is unique per row here so ROWS and RANGE agree, but write the frame anyway — over ungrouped rows with tied timestamps the default RANGE frame pulls in every peer row and the total jumps.
- Newest per aggregate: DISTINCT ON (aggregate_id) ... ORDER BY aggregate_id, aggregate_version DESC is the cheap PostgreSQL-only form when an index matches that order; row_number() OVER (PARTITION BY aggregate_id ORDER BY aggregate_version DESC) = 1 is the portable form and needs a subquery for the same evaluation-order reason as the gap query.
Follow-up
- Relay failover redelivers events. Does a duplicate break the gap query, and how would you detect one from this table alone?
- Turn the gap check into a continuous monitor rather than a query someone runs after an incident. What does it watch?
Walk through the architecture for a real-time message analysis service capable of processing incoming email st
Walk through the architecture for a real-time message analysis service capable of processing incoming email streams without introducing latency.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
How would you design a containerized microservice architecture using cloud-native infrastructure to support hi
How would you design a containerized microservice architecture using cloud-native infrastructure to support high-throughput data processing?
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Explain how you isolate failing services and implement retry mechanisms within distributed cloud environments.
Explain how you isolate failing services and implement retry mechanisms within distributed cloud environments.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Discuss how database schema design choices affect read latency versus write throughput in audit logging applic
Discuss how database schema design choices affect read latency versus write throughput in audit logging applications.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Walk through the most technically complex project you have delivered, highlighting your specific contributions
Walk through the most technically complex project you have delivered, highlighting your specific contributions and architectural decisions.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
How do you approach debugging an intermittent production performance issue in a cloud environment?
How do you approach debugging an intermittent production performance issue in a cloud environment?
Approach
- Establish what changed and when, before forming any theory.
- Pick a bisection that eliminates candidates whichever way it turns out.
- Check the instrumentation before believing the symptom.
- Separate the trigger from the cause; the deploy is rarely the bug.
Follow-up
- What would you look at first, and what would it rule out?
- How would you tell a cause from a coincidence here?
Built from the rounds and topics Tessian candidates report.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Map the Tessian loop
- Write out the reported sequence: Automated Technical Assessment, Recruiter Screen, Code Pair Interview, Virtual Onsite Loop.
- For each round, write one sentence on what it is judging, from the description above, and mark the one you are least ready for.
Deliverable: A one-page map of the 4 reported rounds, with the weakest marked.
02Work Python
- Spend the session on Python, which Tessian candidates report being tested on.
- Write one worked example in Python and time yourself on it.
Deliverable: One timed worked example in Python.
03Work Coding interviews
- Spend the session on Coding interviews, which Tessian candidates report being tested on.
- Write one worked example in Coding interviews and time yourself on it.
Deliverable: One timed worked example in Coding interviews.
04Work Pair programming / code-pairing
- Spend the session on Pair programming / code-pairing, which Tessian candidates report being tested on.
- Write one worked example in Pair programming / code-pairing and time yourself on it.
Deliverable: One timed worked example in Pair programming / code-pairing.
05Answer out loud: Expression Parsing & Core Algorithms
- Answer aloud, timed: Write a program to convert a Prefix (Preorder) mathematical expression into an Infix expression and evaluate its numeric result.
- Answer aloud, timed: Evaluate a Postfix (Reverse Polish Notation) mathematical expression containing variables and basic arithmetic operators.
Deliverable: Spoken answers to 2 reported Expression Parsing & Core Algorithms question(s), under time.
06Answer out loud: Language Fundamentals & Code-Pairing
- Answer aloud, timed: Explain how closures and variable scope hoisting function in JavaScript, and demonstrate how they impact asynchronous execution in `setTimeout`.
- Answer aloud, timed: Discuss Python memory management, built-in data structure implementations, and how dictionary hashing affects lookup performance.
Deliverable: Spoken answers to 2 reported Language Fundamentals & Code-Pairing question(s), under time.
07Answer out loud: Data Structures & String Processing
- Answer aloud, timed: Write a function to parse, clean, and analyze email header strings to detect anomalies within optimal time bounds.
- Answer aloud, timed: Compare the architectural trade-offs between using hash tables, set operations, and sorted arrays for frequent search queries over large string collections.
Deliverable: Spoken answers to 2 reported Data Structures & String Processing question(s), under time.
Expand any day for tasks and deliverables. Your progress is saved on this device.
Behavioural rounds judge the decision you made and what it cost.
Describe a situation where you had to compromise between quick delivery and technical debt, and explain how yo
Describe a situation where you had to compromise between quick delivery and technical debt, and explain how you managed the aftermath.
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
Share an instance where you received critical code review feedback and how you incorporated it into your engin
Share an instance where you received critical code review feedback and how you incorporated it into your engineering practice.
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
Narrate an outage you owned from page to postmortem
Pick an incident you personally drove, ideally one where writes were affected rather than reads. In six to eight minutes: state the symptom as it first appeared on a dashboard, the blast radius you established before you knew the cause, the mitigation you applied and when, the mechanism you eventually proved, and the follow-up that would prevent a repeat. Bring numbers: error rate, tenants affected, minutes to mitigate, minutes to resolve. If you cannot name what you measured, choose a different incident.
Approach
- Open on the signal rather than the cause: which metric at which percentile moved, on which service, at what time, so the listener follows the same evidence you had rather than a conclusion you already reached.
- Separate mitigation from diagnosis out loud. State what you did to stop the bleeding (flag off, shed traffic, drain a lease, roll back a deploy) and say plainly that you did it before the mechanism was known, because those are two jobs with different deadlines.
- Establish blast radius in countable terms: how many tenants, how many writes, and crucially whether the effect was loss or only delay. An append-only revision table or a pending outbox row means the change survived and the projection was merely behind, which is a repair rather than a data-loss incident.
- Prove the mechanism instead of asserting it. Name the trace span that grew, the plan that flipped to a sequential scan, the lease that expired, plus one alternative you ruled out and the signal that stayed flat while you ruled it out.
Follow-up
- What would you do differently in the first five minutes, given the same dashboard and no more information?
- Which follow-up action did you deliberately not take, and why was dropping it the right call?
- 01
Describe a situation where you had to compromise between quick delivery and technical debt, and explain how you managed the aftermath.
- 02
Share an instance where you received critical code review feedback and how you incorporated it into your engineering practice.
- 03
Pick an incident you personally drove, ideally one where writes were affected rather than reads. In six to eight minutes: state the symptom as it first appeared on a dashboard, the blast radius you established before you knew the cause, the mitigation you applied and when, the mechanism you eventually proved, and the follow-up that would prevent a repeat. Bring numbers: error rate, tenants affected, minutes to mitigate, minutes to resolve. If you cannot name what you measured, choose a different incident.
What programming language should I use during the technical interviews?
Tessian primarily uses Python and TypeScript/React internally. However, for initial algorithmic challenges and live coding, you can generally select the language you are most comfortable with. Demonstrating deep proficiency and writing clean idiomatic code in your chosen language is key.
Tessian Software Engineer candidate reports ↗How strict is the time threshold on the initial automated test?
Correctness and time/space complexity are both critical. Your code must pass all hidden unit test cases without timing out or exceeding memory limits. Taking time to double-check edge cases before submitting is highly recommended.
Tessian Software Engineer candidate reports ↗What is the atmosphere like during the live code-pairing interview?
Candidates describe the code-pairing rounds as collaborative discussions. Interviewers expect you to think out loud, explain your strategy, and converse naturally while implementing your solution.
Tessian Software Engineer candidate reports ↗Does Tessian ask abstract LeetCode-style questions or domain-specific problems?
While initial screening assessments cover foundational computer science algorithms (such as parsing or array manipulation), live technical interviews lean toward domain-relevant, practical software engineering problems (such as string manipulation, data structure trade-offs, and microservice APIs).
Tessian Software Engineer candidate reports ↗How quickly does Tessian move between interview stages?
Stage progression is typically fast-moving, with feedback often communicated within a few business days between stages. Communication is managed by the talent acquisition team over email or video calls.
Tessian Software Engineer candidate reports ↗How hard is the Tessian interview?
Candidates most commonly rate Tessian interviews as medium, based on 265 reported interviews. About 34% of candidates who interview go on to receive an offer.
Tessian Software Engineer candidate reports ↗What topics does Tessian test in interviews?
Tessian interviews most often cover Problem Solving, Python, Time Management, Adaptability, and System Design. The exact emphasis depends on the specific role you apply for.
Tessian Software Engineer candidate reports ↗Is Tessian a good place to work?
Employees rate Tessian 4.7 out of 5 overall, based on aggregated workplace reviews spanning career growth, work-life balance, compensation, culture, and management.
Tessian Software Engineer candidate reports ↗Where is Tessian headquartered?
Tessian is headquartered in London, United Kingdom.
Tessian Software Engineer candidate reports ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01Tessian Software Engineer candidate reports ↗
Company-reported rounds, questions and FAQ.
candidate · Accessed 2026-09-22 - 02PracHub Software Engineer practice ↗
PracHub practice material, not company-reported.
platform · Accessed 2026-09-22 - 03PracHub preparation framework ↗
PracHub preparation guidance.
platform · Accessed 2026-09-22