A Software Engineer at Stifel Financial plays a critical role in building, optimizing, and maintaining the financial technology systems that power one of the nation’s leading wealth management and investment banking firms. Technology is at the core of Stifel Financial's operations, enabling financial advisors, analysts, and clients to make data-driven decisions securely and efficiently. Whether you are embedded in the Tech Product Development (TPD) division or supporting critical infrastructure in IT Operations, your work directly impacts the reliability and speed of financial transactions. In this role, you will work on a diverse array of platforms, ranging from proprietary wealth management applications to high-performance data pipelines and secure web portals. The engineering challenges here are unique, requiring a balance between modern software development practices and the strict regulatory, security, and performance standards of the financial services industry. You will collaborate closely with product managers, network architects, and system administrators to design solutions that are resilient under high loads and secure against modern threats. For candidates, this means joining an organization where engineering is viewed as a strategic driver of business success rather than a back-office support function.
Initial Screening
reportedConducted by an internal Talent Coach or Hiring Manager, focusing on work history, technical interests, and motivation.
What to demonstrate
- Conducted by an internal Talent Coach or Hiring Manager
- Focusing on work history, technical interests, and motivation
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.
Technical and Panel Interview
reportedInvolves senior developers or engineering managers assessing technical capabilities, past projects, and problem-solving methodologies.
What to demonstrate
- Involves senior developers or engineering managers assessing technical capabilities, past projects, and problem-solving methodologies
- Depth in Data Structures and Algorithms (DSA)
How to prepare
- Answer aloud and timed: Describe a design pattern you have used to solve a complex software architecture problem (e.g., Singleton, Factory, or Observer).
- Answer aloud and timed: How do you ensure code reusability and maintainability when designing a new software component?
PracHub editorial advice for the preparation topics above.
Showcase your collaborative nature
Stifel highly values team player dynamics. Avoid sounding like a lone-wolf developer; instead, emphasize how you collaborate with product managers, QA engineers, and operations teams to ship great software.
Brush up on the basics
Do not neglect fundamental concepts like the difference between abstract classes and interfaces, or how basic data structures work under the hood. Getting these right builds immediate credibility.
Be prepared for potential variation in interviewer styles
While most panels are highly professional and welcoming, some candidates have reported encountering more direct or challenging interviewers. Stay calm, confident, and professional throughout your conversations.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Walk through how you would implement a singly linked list and write a function to reverse it.
Walk through how you would implement a singly linked list and write a function to reverse it.
Approach
- Model a
Nodewithvalandnext, and a list holdingheadplus atailpointer andsize, so append is O(1) instead of an O(n) walk; search and delete by value stay O(n). - Reverse iteratively with two pointers and a temp: start
prev = None,curr = head; each step savenxt = curr.next, setcurr.next = prev, then advanceprev = curr,curr = nxt. WhencurrisNone,previs the new head. - Complexity: O(n) time and O(1) extra space. The recursive version is also O(n) time but uses O(n) call-stack space and hits Python's default recursion limit at around a thousand nodes.
- Guard the cases that break naive code: empty list, one node, two nodes. Rewiring
curr.nextbefore saving it loses the rest of the list, and forgetting to movetailleaves later appends attached to the wrong node. - Verify by building from a Python list and converting back, and check that reversing twice returns the original order.
Worked solution 15 min
In-place iterative reversal
- Write
Nodeand aLinkedListwhose constructor appends from any iterable, which makes test setup a one-liner. appendlinks the new node aftertail(or sets bothheadandtailwhen empty), keeping it O(1).reversefirst records that the current head will become the tail, then flips eachnextpointer in a single pass.to_listwalks fromhead, which is how the checks compare results against plain Python lists.
class Node:
def __init__(self, val, next=None):
self.val = val
self.next = next
class LinkedList:
def __init__(self, values=()):
self.head = None
self.tail = None
self.size = 0
for v in values:
self.append(v)
def append(self, val):
"""O(1) thanks to the tail pointer."""
node = Node(val)
if self.tail is None:
self.head = self.tail = node
else:
self.tail.next = node
self.tail = node
self.size += 1
def to_list(self):
out, curr = [], self.head
while curr:
out.append(curr.val)
curr = curr.next
return out
def reverse(self):
"""Reverse in place: O(n) time, O(1) extra space."""
prev, curr = None, self.head
self.tail = self.head # the old head becomes the tail
while curr:
nxt = curr.next # save the rest before rewiring
curr.next = prev
prev, curr = curr, nxt
self.head = prev
Scroll sideways to view long lines.
Follow-up
- Can you reverse it recursively? Reverse the rest from
head.next, then sethead.next.next = headandhead.next = None; it costs O(n) stack space. - How would you reverse only positions m to n? Walk to the node before position m, reverse the next n - m + 1 nodes with the same pointer loop, then reconnect both ends.
- How do you detect a cycle before reversing? Floyd's slow/fast pointers: if they ever meet there is a cycle. O(n) time, O(1) space.
How do binary search trees differ from hash tables in terms of lookup, insertion, and deletion time complexiti
How do binary search trees differ from hash tables in terms of lookup, insertion, and deletion time complexities?
Approach
- Hash table: lookup, insert and delete are O(1) on average (expected), assuming a decent hash function and a load factor kept bounded; worst case is O(n) when many keys land in one bucket, through bad hashing or adversarial keys.
- Insertion is O(1) amortized: when the load factor passes a threshold the table grows (typically doubling) and rehashes every entry, an O(n) step spread across the many cheap inserts before it.
- BST: all three operations are O(h), where h is the tree height. A self-balancing tree (AVL, red-black) keeps h = O(log n) in the worst case; a plain BST fed keys in sorted order degenerates into a linked list with h = n.
- BST deletion has three cases: a leaf is removed; a node with one child is replaced by that child; a node with two children copies its in-order successor's key (the right subtree's minimum), then deletes that successor, which has at most one child. Balanced trees then rotate, still O(log n).
- State what a BST buys that a hash table cannot: sorted iteration, min/max, floor/ceiling and range queries in O(log n + k). A hash table is unordered, so a range query means scanning every entry.
- Anchor it in real libraries: Java
HashMapversusTreeMap(red-black), C++unordered_mapversusstd::map. Java 8+HashMapalso turns a bucket that passes 8 entries into a red-black tree once the table has 64+ slots, so a crowded bucket costs O(log n) forComparablekeys.
Follow-up
- When would you choose a BST despite slower lookups? When you need sorted order or range queries (all keys between two timestamps) or a guaranteed worst case instead of an expected one.
- Why is a hash table's worst case O(n)? If every key hashes to one bucket, that bucket becomes a list to scan; randomised or keyed hash seeds make that hard for an attacker to force.
- What keeps a red-black tree balanced? Colour rules enforced with rotations and recolouring after each insert or delete, which bound height at 2·log2(n+1).
Given an array of integers, how would you find the duplicate elements in linear time?
Given an array of integers, how would you find the duplicate elements in linear time?
Approach
- Interpret it as: return each value that occurs more than once, reported once. Confirm whether order matters, whether indices or values are wanted, and whether the input may be modified.
- Key insight: a hash set gives O(1) expected membership, so one pass works. If
xis already inseenit is a duplicate; a secondreportedset stops a value that appears three times from being listed twice. - Complexity: O(n) expected time and O(n) extra space. Sorting first is O(n log n) and nested loops are O(n²), so neither meets the linear requirement.
- If values lie in 1..n, use the array itself as the table for O(1) extra space: negate
nums[abs(x)-1](reports a triple twice) or addnto that slot and read the count as(v - 1) // n, then restore the input. In Java or C# a slot can reach n + n², so uselong. - Edge cases: empty array, no duplicates, a value repeated three or more times, negative numbers or huge values (fine for a set, fatal for the index trick), and input too large for memory.
Worked solution 15 min
Hash-set scan with an in-place variant
find_duplicateskeepsseenfor values met once andreportedfor values already emitted, appending todupesonly on a value's first repeat.- This preserves the order of first repeat and handles negatives, zero and large values, since a set does not care about the range.
find_duplicates_boundedapplies only when every value is in 1..n: each value addsnto its own slot, and(x - 1) % n + 1recovers a value even if its slot was already bumped.- A slot whose count
(v - 1) // nis at least 2 is a duplicate; a final pass restores every entry, so the caller's array is unchanged.
def find_duplicates(nums):
"""Each value that appears more than once, reported once, in the
order its first repeat is seen. O(n) expected time, O(n) space."""
seen, reported, dupes = set(), set(), []
for x in nums:
if x not in seen:
seen.add(x)
elif x not in reported:
reported.add(x)
dupes.append(x)
return dupes
def find_duplicates_bounded(nums):
"""Only when every value lies in 1..len(nums). O(n) time, O(1)
extra space: tallies counts inside the array, then restores it."""
n = len(nums)
for x in nums:
orig = (x - 1) % n + 1 # value even if its slot was bumped
nums[orig - 1] += n
dupes = [i + 1 for i in range(n) if (nums[i] - 1) // n >= 2]
for i in range(n):
nums[i] = (nums[i] - 1) % n + 1 # undo the tallies
return dupes
Scroll sideways to view long lines.
Follow-up
- What if the data does not fit in memory? Hash-partition values into k files by
hash(x) % kso equal values share a partition, then find duplicates in each partition in memory. - How would you return how many times each duplicate occurs? Build
collections.Counter(nums)and keep entries with count > 1; still O(n). - What if exactly one value repeats in an array of n + 1 values from 1..n and you can't modify it? Treat
i -> nums[i]as a linked list and use Floyd's cycle detection; the cycle entry is the duplicate.
Explain the concept of recursion and walk through a scenario where recursion is preferable to iteration.
Explain the concept of recursion and walk through a scenario where recursion is preferable to iteration.
Approach
- Define it precisely: a recursive function solves a problem by calling itself on a smaller instance until it reaches a base case answered directly. It needs both a base case and progress toward it, or it recurses until the stack overflows.
- Explain the cost: every call pushes a stack frame holding its locals and return address, so space is O(depth). CPython caps depth at about 1000 by default (
sys.getrecursionlimit()), and neither CPython nor the JVM eliminates tail calls. - Recursion is preferable when the problem is itself recursive: trees and nested data (JSON, directories, org charts), divide and conquer (merge sort, quicksort), and backtracking (permutations, subsets). An iterative version has to rebuild the call stack by hand.
- Iteration wins for linear work (summing a list, walking a linked list), for inputs deep enough to overflow the stack, and in hot loops. Naive recursion with overlapping subproblems, like
fib(n), is exponential until memoized or rewritten bottom-up. - Walk through a scenario: flattening an arbitrarily nested list. The base case is a non-list element, which is emitted; the recursive case flattens each child. Nesting depth is unknown in advance, so a fixed set of loops cannot do it.
- Close with the caveat: any recursion can be converted to iteration with an explicit stack, so recursion is never required. You choose it for clarity and correctness, and fall back to the stack version when depth is unbounded.
Worked solution 15 min
Flatten nested lists recursively
flattendefines an innerwalkthat appends leaves to one sharedoutlist, which avoids re-copying partial results on every level.- Lists and tuples are containers; everything else, including strings, is a leaf. That stops a string from being split into characters.
flatten_iterativeproduces the same output with a stack of iterators:breakpushes a child container, and thefor/elsepops an iterator once it is exhausted.- Comparing the two versions is the argument: the recursive one mirrors the data's shape in a few lines, while the iterative one exists for inputs deeper than the recursion limit.
def flatten(nested):
"""Recursively flatten arbitrarily nested lists/tuples.
O(total elements) time; O(depth) call-stack space."""
out = []
def walk(item):
if isinstance(item, (list, tuple)):
for child in item: # recursive case: a smaller piece
walk(child)
else:
out.append(item) # base case: a leaf value
walk(nested)
return out
def flatten_iterative(nested):
"""Same result with an explicit stack of iterators: no recursion
limit, but we now hand-manage what the call stack did for free."""
out, stack = [], [iter([nested])]
while stack:
for item in stack[-1]:
if isinstance(item, (list, tuple)):
stack.append(iter(item))
break
out.append(item)
else:
stack.pop()
return out
Scroll sideways to view long lines.
Follow-up
- What is tail recursion, and does it help in Python? A tail call is the function's last action, so a compiler could reuse the frame, but CPython does not, so depth still costs stack.
- How would you speed up naive recursive Fibonacci?
functools.lru_cachegives O(n) time but still recurses n deep, so a coldfib(1500)raisesRecursionError; a bottom-up loop with two variables is O(n) time, O(1) space. - What if the input is nested 100,000 levels deep? The recursive version raises
RecursionError; use the explicit-stack version, whose stack lives on the heap.
Write the update path that detects a concurrent edit
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?
Denormalise tenant onto revisions and backfill it live
resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.
Approach
- Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
- Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
- Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
- Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.
Follow-up
- The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
- How do you verify the backfill actually finished, given rows are still being inserted while it runs?
Explain the four pillars of Object-Oriented Programming and how you have applied them in a recent project.
Explain the four pillars of Object-Oriented Programming and how you have applied them in a recent project.
Approach
- Encapsulation bundles state with the methods that guard it and hides the internals, so an object's invariants can only change through its own methods (e.g. a
balancethat is private and only moves throughdeposit()/withdraw()with validation). - Abstraction exposes what an object does, not how: callers see a small contract like
Notifier.send(message)and never touch the SMTP client or retry logic behind it. - Inheritance lets a subclass reuse and extend a base type in an is-a relationship; polymorphism lets code written against a base type or interface run any subtype, with the method picked at runtime by the object's actual type (dynamic dispatch).
- Separate encapsulation from abstraction explicitly, since mixing them up is the classic weak answer: encapsulation is about protecting state and access, abstraction is about the level of detail in the interface. Getters and setters on every field are not encapsulation; they leak state.
- Add the caveat a senior answer includes: inheritance couples a subclass to its parent's internals (fragile base class), so favour composition plus interfaces, and only subclass when the Liskov substitution principle genuinely holds.
- For the project half, pick one real component and map each pillar to a decision you made and what it bought, e.g. "an exporter interface with CSV and PDF implementations chosen at runtime replaced a growing
if/else, so a new format touched one new class."
Follow-up
- What is the difference between overloading and overriding? Overloading picks a method by parameter signature at compile time; overriding replaces a base-class method and is resolved at runtime by the object's actual type.
- Why prefer composition over inheritance? Composition lets you swap behaviour at runtime and keeps each class's surface small, while inheritance exposes the subclass to every change in the parent.
- How is encapsulation enforced in Python, which has no
private? Only by convention:_namemarks internal,__nametriggers name mangling and@propertyvalidates on assignment, none of which stops determined access.
What is the difference between an abstract class and an interface, and when would you choose one over the othe
What is the difference between an abstract class and an interface, and when would you choose one over the other?
Approach
- Answer in Java/C# terms and say so: an interface is a contract (a capability) any class can implement, and a class can implement many; an abstract class is a partially built base class that cannot be instantiated, and a class can extend only one.
- Contrast what each holds: an abstract class can have instance fields, constructors and members at any access level. An interface has no instance state or constructors, only abstract methods and
public static finalconstants, plusdefaultandstaticmethods (Java 8+) andprivatemethods (Java 9+). - Name the outdated misconception: "interfaces can't contain implementation" stopped being true with Java 8 default methods and C# 8 default interface members. The real remaining differences are state, constructors and the single-inheritance slot.
- Choose an interface for a role that unrelated types play (
Comparable,AutoCloseable, aRepository), for dependency injection and test doubles, and whenever implementers may need to extend some other class. It is the default for public contracts. - Choose an abstract class when closely related types share state and code, or for the template method pattern: the base class fixes the algorithm's skeleton in a
finalmethod and subclasses fill in abstract hook steps. - Mention the combined idiom: define the contract as an interface and ship an optional abstract skeletal implementation next to it (
ListplusAbstractListin the Java collections) so implementers get reuse without losing flexibility.
Follow-up
- What if a class implements two interfaces with the same default method? Java refuses to compile until the class overrides it; inside the override it can pick one with
A.super.method(). - How does Python express the same idea?
abc.ABCwith@abstractmethodcovers the abstract-class case;typing.Protocolgives structural interfaces checked by type checkers, not at runtime unless marked@runtime_checkable. - Why give an abstract class a constructor if it can't be instantiated? Subclasses call it through
super(...), so it initialises the shared fields and enforces their invariants in one place.
Describe a design pattern you have used to solve a complex software architecture problem (e.g., Singleton, Fac
Describe a design pattern you have used to solve a complex software architecture problem (e.g., Singleton, Factory, or Observer).
Approach
- Pick the pattern that solved a real problem you owned, not the one you can define best. Singleton is the riskiest choice, since its downsides (hidden global state, hard-to-mock dependencies, lazy-init races) invite pointed follow-ups.
- Know the three named patterns precisely: Singleton guarantees one instance with a global access point; Factory centralises creation so callers depend on an interface, not a concrete class; Observer has a subject notify registered listeners on state change.
- Open with the forces before the pattern: what kept changing and what was coupled, e.g. "every new consumer of an order-status change meant editing the producer" motivates Observer, and a growing
switchon a type code motivates a Factory. - Show the structure you built: the interface, the concrete classes, how instances were chosen (a registry map keyed by config instead of
if/else), who registers observers and when, and how it behaved under concurrency. - State the tradeoffs you managed: Observer leaks memory when listeners never unsubscribe, one throwing listener can stop the rest, and synchronous notification makes the producer as slow as its slowest listener; a Factory adds indirection that must earn its keep.
- Close with evidence and hindsight: what got cheaper (e.g. adding a variant went from editing four files to adding one class), bugs or test time it removed, and what you would change now.
Follow-up
- How would you make a lazy Singleton thread-safe in Java? Use the holder-class idiom or an
enum(double-checked locking works only with avolatilefield), or let the DI container own the single instance. - How is Observer different from publish/subscribe? In Observer the subject holds direct references to observers, usually in-process; pub/sub puts a broker between them so neither side knows the other, often asynchronously.
- Factory Method or Abstract Factory? Factory Method lets a subclass decide which single product to create; Abstract Factory creates whole families of related objects through one interface.
How do you ensure code reusability and maintainability when designing a new software component?
How do you ensure code reusability and maintainability when designing a new software component?
Approach
- Start from the boundary: give the component one responsibility and a small public API, decide what it owns versus what it depends on, and keep everything else private so callers cannot couple to internals.
- Put abstractions at the seams: inject the database, clock, HTTP client and config through the constructor instead of reaching for globals or static calls, so each can be swapped in production and faked in tests.
- Reuse by composition and clear contracts, not speculative generality. Extract a shared abstraction once a third real use appears (rule of three); a wrong abstraction costs more than a little duplication.
- Test the public contract rather than private methods, so refactors that keep behaviour do not break tests; run tests, linters and static analysis in CI so the standard holds without relying on memory.
- Make change cheap for the next reader: consistent naming, small functions, explicit types and error handling at the boundary, and a short design note recording why key decisions were made.
- If the component is shared, version it: semantic versioning, a changelog, and deprecating an API for one release before removing it. Then name one component of yours where this paid off and the signal that showed it, such as fewer consumer breakages.
Follow-up
- How do you avoid over-engineering? Build for today's requirement plus the one variation you can actually name, and for each hook or config option ask who calls it today; if no one does, it is speculative and should go.
- How can you tell a component has become hard to maintain? Small changes touch many files, or tests break on refactors that did not change behaviour; both mean internals are leaking.
- How do you change a widely used shared library safely? Add the new path alongside the old one, mark the old one deprecated, and run consumers' contract tests before the breaking release.
Walk us through the layers of the OSI model and explain the primary responsibility of each layer.
Walk us through the layers of the OSI model and explain the primary responsibility of each layer.
Approach
- L1 Physical moves raw bits over a medium (voltage, light, radio; cables, hubs). L2 Data Link moves frames between directly connected nodes using MAC addresses and detects errors with a CRC (Ethernet, Wi-Fi, switches).
- L3 Network moves packets between networks with logical addressing and routing (IP, ICMP, routers). L4 Transport delivers data end to end between processes identified by ports: TCP adds reliability, ordering, flow and congestion control; UDP does not.
- L5 Session sets up, manages and tears down dialogs between applications. L6 Presentation handles representation: encoding, serialization, compression and encryption. L7 Application holds the protocols applications speak (HTTP, DNS, SMTP), not the applications themselves.
- Explain encapsulation: going down the stack each layer wraps the payload with its own header (segment, then packet, then frame, then bits), and the receiver strips them in reverse, so each layer talks logically only to its peer.
- Show you know OSI is a reference model: the internet runs the TCP/IP model (link, internet, transport, application), which folds L5 to L7 into one application layer. TLS and ARP do not fit one OSI layer cleanly; say so rather than forcing them.
- Make it practical: troubleshoot bottom-up by layer, with link lights and cabling (L1), MAC tables, VLANs and ARP (L2), IP and routes with
ping(L3), port reachability withnc(L4), then TLS and HTTP status (L6 and L7).
Follow-up
- Where does a load balancer sit? An L4 balancer forwards by IP and port without reading payloads; an L7 balancer terminates the connection and routes on HTTP host, path or headers.
- At which layers do switches and routers work? Switches forward frames by MAC address (L2), routers forward packets by IP between networks (L3), and L3 switches do both.
- What does ARP do? It broadcasts on the local segment to find the MAC address that owns an IPv4 address so a frame can be addressed; IPv6 uses Neighbor Discovery instead.
What is the difference between TCP and UDP, and in what scenarios would you choose one over the other?
What is the difference between TCP and UDP, and in what scenarios would you choose one over the other?
Approach
- TCP is connection-oriented (SYN, SYN-ACK, ACK handshake) and delivers a reliable, ordered byte stream using sequence numbers, acknowledgements and retransmission, plus flow control (receive window) and congestion control.
- UDP is connectionless: independent datagrams with no delivery, ordering or duplicate guarantees and no congestion control, behind an 8-byte header versus TCP's 20 to 60 bytes.
- Name TCP's costs: a round trip before any data (more with TLS), retransmission delays, and head-of-line blocking where one lost segment stalls every byte behind it. Also note TCP is a stream, so the application must frame messages; UDP keeps message boundaries.
- Choose TCP when every byte must arrive in order: web APIs over HTTP/1.1 and HTTP/2, database connections, file transfer, SSH, and anything like order or transaction messages where a gap is unacceptable.
- Choose UDP when timeliness beats completeness or exchanges are tiny: DNS lookups, voice and video calls, games, streaming telemetry, and multicast (TCP cannot multicast). QUIC, the transport under HTTP/3, builds reliability per stream on UDP.
- Correct two misconceptions: UDP is not simply faster, since the application inherits loss, reordering, duplication and congestion handling; and a TCP ACK only proves the peer's kernel received bytes, not that the application processed them.
Follow-up
- Why does DNS use UDP but sometimes switch to TCP? Most answers fit in one datagram, avoiding a handshake; truncated responses (TC bit set) and zone transfers go over TCP.
- How would you add reliability on top of UDP? Sequence numbers, ACKs with timeouts and retransmission, receiver-side de-duplication and some congestion control, or simply use QUIC instead of reinventing it.
- What happens to TCP throughput on a lossy link? Loss is read as congestion, so the sender shrinks its congestion window; even small loss rates cut throughput sharply on high-latency paths.
How does routing work across a local area network versus a wide area network?
How does routing work across a local area network versus a wide area network?
Approach
- Interpret "routing on a LAN" carefully: traffic inside one subnet is not routed at all. The host sees the destination is on-link via its subnet mask, uses ARP to get the destination's MAC, and switches forward the frame using MAC tables learned from source addresses.
- Leaving the subnet, the host sends the frame to its default gateway's MAC while the IP destination stays the remote host. Each router picks the next hop by longest-prefix match in its routing table, decrements TTL and re-frames the packet, so MACs change per hop and IPs do not (NAT aside).
- Within one organisation, routers learn routes statically or via interior protocols: OSPF (link-state, Dijkstra on link costs) or RIP (distance-vector, hop count capped at 15). VLANs split a LAN into broadcast domains, and traffic between them needs a router or an L3 switch.
- Across a WAN, sites connect over carrier circuits, MPLS, SD-WAN or IPsec VPN tunnels over the internet. Between autonomous systems on the internet, BGP (path-vector) picks routes by policy such as local preference and AS-path length, not just the shortest path.
- Close with the contrast: a LAN is one administrative domain with high bandwidth, low latency and broadcast-based discovery; a WAN has higher latency and cost, several administrators, NAT and firewalls at the edge, and route convergence to worry about.
Follow-up
- What is longest-prefix match? When several routes cover a destination, the router uses the most specific (a /24 beats a /16) and falls back to the default route 0.0.0.0/0.
- Why does NAT usually sit at the WAN edge? Private RFC 1918 addresses are not routable on the internet, so the edge device rewrites source address and port to a public one and tracks the mapping.
- How would you see the path a packet takes?
traceroutesends probes with increasing TTL; each router that drops one returns ICMP Time Exceeded, revealing every hop and its latency.
Describe how you would troubleshoot a sudden drop in application performance that appears to be network-relate
Describe how you would troubleshoot a sudden drop in application performance that appears to be network-related.
Approach
- Scope before touching anything: which metric dropped (p50 vs p99 latency, throughput, timeouts), since when, and for whom (every user, one site or region, one downstream call). Line the start time up against deploys, firewall or DNS changes, certificate renewals and carrier work.
- Prove it is the network: if server-side processing time is flat while client-observed latency rose, the time is going in the path. Mitigate first if users are hurting: roll back the change, fail over to another link or region, and cap retries so they don't turn into a storm.
- Find which phase grew with
curl -wtimings (DNS lookup, TCP connect, TLS handshake, time to first byte). Slow DNS points at the resolver or a changed record; slow connect points at the path or a saturated listener; slow first byte with a fast connect points back at the server. - Check path health:
mtrortracerouteshows the hop where latency or loss starts,ss -tiandnetstat -sshow TCP retransmits,ip -s linkshows interface errors and drops. Even 1 to 2% loss collapses TCP throughput. - Rank the usual suspects and confirm each: a saturated link (utilisation graphs), a flaky link (retransmits, CRC errors), an MTU mismatch after a VPN or tunnel change (large transfers stall,
ping -M do -s 1472fails), and NAT, conntrack or ephemeral-port exhaustion (connect failures under load). - Capture with
tcpdumpon both ends if still unclear: retransmits and duplicate ACKs mean loss; a zero window means a slow receiving app; RSTs mean something refused or aborted the connection (a firewall, a load balancer idle timeout, or the server itself), and the two captures show who sent them.
Follow-up
- How would you prove DNS is the culprit? Time lookups with
digagainst the configured resolver and a known-good one; if only the configured one is slow, check its health, cache hit rate and recent record or TTL changes. - What if only some users are affected? Group the failures by region, office, ISP, resolver or client version; a shared attribute points at one link, edge node or DNS server.
- Why would an MTU problem only hurt large responses? If ICMP "fragmentation needed" is blocked, packets bigger than the path MTU are silently dropped, so small requests work while big payloads hang.
Built from the rounds and topics Stifel Financial candidates report.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Map the Stifel Financial loop
- Write out the reported sequence: Initial Screening, Technical and Panel Interview.
- 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 2 reported rounds, with the weakest marked.
02Work Data Structures and Algorithms (DSA)
- Spend the session on Data Structures and Algorithms (DSA), which Stifel Financial candidates report being tested on.
- Write one worked example in Data Structures and Algorithms (DSA) and time yourself on it.
Deliverable: One timed worked example in Data Structures and Algorithms (DSA).
03Work Object-Oriented Programming (OOP)
- Spend the session on Object-Oriented Programming (OOP), which Stifel Financial candidates report being tested on.
- Write one worked example in Object-Oriented Programming (OOP) and time yourself on it.
Deliverable: One timed worked example in Object-Oriented Programming (OOP).
04Work Behavioral interview questions
- Spend the session on Behavioral interview questions, which Stifel Financial candidates report being tested on.
- Write one worked example in Behavioral interview questions and time yourself on it.
Deliverable: One timed worked example in Behavioral interview questions.
05Answer out loud: Object-Oriented Programming (OOP) & Design Patterns
- Answer aloud, timed: Explain the four pillars of Object-Oriented Programming and how you have applied them in a recent project.
- Answer aloud, timed: What is the difference between an abstract class and an interface, and when would you choose one over the other?
Deliverable: Spoken answers to 2 reported Object-Oriented Programming (OOP) & Design Patterns question(s), under time.
06Answer out loud: Data Structures & Algorithms (DSA)
- Answer aloud, timed: Walk through how you would implement a singly linked list and write a function to reverse it.
- Answer aloud, timed: How do binary search trees differ from hash tables in terms of lookup, insertion, and deletion time complexities?
Deliverable: Spoken answers to 2 reported Data Structures & Algorithms (DSA) question(s), under time.
07Answer out loud: Systems & Networking (Role-Dependent)
- Answer aloud, timed: Walk us through the layers of the OSI model and explain the primary responsibility of each layer.
- Answer aloud, timed: What is the difference between TCP and UDP, and in what scenarios would you choose one over the other?
Deliverable: Spoken answers to 2 reported Systems & Networking (Role-Dependent) 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.
Walk me through your resume and highlight a project where you had to overcome a significant technical roadbloc
Walk me through your resume and highlight a project where you had to overcome a significant technical roadblock.
Approach
- A strong answer does two things: tells your career as a coherent story in about two minutes, and proves you personally have real technical depth. Reading the resume line by line fails the first; a vague project fails the second.
- Give the walk-through a thread: for each role say the scope, the stack and one result, and end on why this role is the logical next step. Keep it short so most of the time goes to the project.
- Choose a roadblock that was technical and that you drove, e.g. "a nightly batch that grew from 20 minutes to 4 hours as volume tripled." Avoid blockers that were purely organisational or that a colleague solved.
- Hit the beats in order: why it mattered (users, deadline, cost), the exact symptom, how you diagnosed it (hypotheses, data gathered, dead ends ruled out), the options you weighed and why you chose one, and how you rolled it out safely.
- Quantify the before and after (runtime, latency, error rate, cost, hours saved), say "I" for your own work while crediting the team fairly, and name one thing you would do differently.
- Vet every technology on the resume before the interview: for each, be ready to explain why you chose it and how it works one layer down, and drop anything you cannot defend.
Follow-up
- Why that solution over the alternatives? Name the two options you rejected and the specific constraint (time, risk, cost, skills) that ruled each one out.
- How did you know the fix really worked? Point to the before and after metric and how long you watched it in production before calling it done.
- What if your fix had failed in production? Describe the rollback path or feature flag you had ready and how quickly you could have reverted.
Tell me about a time you had to work with a difficult team member or resolve a technical disagreement.
Tell me about a time you had to work with a difficult team member or resolve a technical disagreement.
Approach
- Show you can disagree without damage: separate the person from the problem, argue with evidence, and commit once a decision is made. A technical disagreement (a data store choice, an API shape) usually makes a better story than a personality clash, which tends to sound like blame.
- Describe the other person's position fairly, including the good reason behind it. If they come across as simply wrong or difficult, the answer backfires, however the story ends.
- Show the actions: a private conversation first, agreeing on the shared goal and the decision criteria (latency, cost, delivery date), then settling it with data such as a prototype, benchmark or spike, and escalating only with both views written up if you stayed stuck.
- Give the resolution plainly: whose approach won or what hybrid emerged, the measurable outcome, and how the working relationship looked afterwards. A story where the evidence proved you wrong and you changed course can be the strongest version.
- End with what you do differently now, e.g. writing the decision criteria into the design doc before debating options, so the lesson is concrete.
- Avoid gossip, "I was right and they gave in," conflicts left unresolved with no lesson, and going to a manager or HR as the first move.
Follow-up
- What if you had been overruled? Commit fully to the decision, write down your concern and the metric that would show a problem, and reopen it only if the data does.
- How would you handle a teammate who keeps missing commitments? Talk privately about specific instances and their impact, ask what is blocking them, agree smaller checkpoints, and involve the manager only if it continues.
- How would the other person describe that disagreement? Answer with feedback you actually received or how you worked together afterwards, not a guess that flatters you.
Why are you interested in joining Stifel Financial, and how does this role align with your long-term career go
Why are you interested in joining Stifel Financial, and how does this role align with your long-term career goals?
Approach
- A strong answer shows you researched the firm and the role and that the job fits your path. Anything that could be said about any employer ("great culture, big name") fails.
- Use three parts: why this firm, why this role, why now. For the firm, cite one or two specifics you checked yourself in its public materials or the job posting, and claim nothing you cannot back up.
- For the role, map two or three requirements from the job description to things you have done, so interest turns into evidence of fit.
- If the financial domain genuinely draws you, say exactly what, e.g. "I want to work on software where correctness and security are hard requirements," and link it to something you have built or studied.
- Make long-term goals specific and compatible with the role, e.g. deeper ownership of backend systems and later leading a small team, and show this job is a step on that path rather than a stopgap.
- Avoid leading with pay or stability, reciting the About page, or guessing at internal systems. Finish with a sincere question about the team's current priorities.
Follow-up
- What do you know about the team you would join? Summarise what the job description and earlier conversations told you, then ask a specific question instead of guessing.
- What have you done recently to move toward that goal? Name one concrete step, such as a stretch assignment, a course or a side project, and what it changed in how you work.
- What else are you considering? Answer briefly and honestly at the level of the kind of role you're looking at, then restate what makes this one stand out for you.
How do you handle a situation where you are asked to deliver a feature under a tight deadline with incomplete
How do you handle a situation where you are asked to deliver a feature under a tight deadline with incomplete requirements?
Approach
- Show judgment under ambiguity: clarify, cut scope, surface risk and still ship; weekend heroics are not the answer. Anchor it in one real feature you delivered this way.
- Open with the first move: find out what is driving the deadline (a client commitment, a regulatory date, a demo) and the one outcome that must work, list the open questions, and get answers to the ones that block design within a day.
- Write down your assumptions and have the product owner confirm them, then propose a cut into must-have and later, negotiating scope rather than quality. Tests, security checks and error handling stay in.
- Build so late answers are cheap: put uncertain rules behind interfaces, configuration or feature flags, build the settled parts first, and demo thin slices early so requirement gaps show up while there is still time.
- Report risk early and in writing (done, at risk, decisions needed), and take the scope-versus-date trade-off to whoever owns it instead of quietly cutting corners.
- Close with the outcome and follow-through: what shipped, what moved to the next release, defects afterwards, and one process change you made, e.g. a checklist that requirements must pass before sprint commitment. It backfires to skip tests or blame the product manager.
Follow-up
- What if the stakeholder won't cut scope or move the date? Lay out the specific trade-off in writing (which items, what risk) and let the decision owner choose, then record the decision.
- Which corners would you never cut? Anything touching correctness, security or data integrity, such as input validation or audit logging, because failures there cost far more than a slipped date.
- How do you estimate when requirements are incomplete? Give a range tied to named assumptions: firm estimates for the settled parts and a time-boxed spike for the biggest unknown, re-estimated once it is answered.
- 01
Tell me about a time you had to work with a difficult team member or resolve a technical disagreement.
- 02
Why are you interested in joining Stifel Financial, and how does this role align with your long-term career goals?
- 03
How do you handle a situation where you are asked to deliver a feature under a tight deadline with incomplete requirements?
How difficult are the technical interviews at Stifel Financial?
The technical interviews are generally rated as average in difficulty. They focus heavily on practical engineering fundamentals, such as OOP principles, basic data structures, and clean coding practices, rather than highly abstract or complex algorithmic puzzles.
Stifel Financial Software Engineer candidate reports ↗What is the culture like on the technology teams?
The culture is highly collaborative, down-to-earth, and professional. Employees frequently note that their colleagues are approachable and supportive, making it an excellent environment for engineers who value teamwork and mutual respect over competitive silos.
Stifel Financial Software Engineer candidate reports ↗Does Stifel Financial support remote work for Software Engineers?
Stifel Financial generally operates on a hybrid model, combining in-office collaboration with remote flexibility. The exact expectations vary by team and location, so it is best to clarify the current policy with your recruiter during your initial screen.
Stifel Financial Software Engineer candidate reports ↗How fast does the interview process move?
The process is known for being highly streamlined. Many candidates complete their technical and panel interviews in a single afternoon, with final decisions and offers often extended within one to two weeks following the final round.
Stifel Financial Software Engineer candidate reports ↗What topics does Stifel Financial test in interviews?
Stifel Financial interviews most often cover Excel (financial modeling), Equity Research, Business Analysis (Business Analyst role), Walking Through Resume, and Data Structures and Algorithms (DSA). The exact emphasis depends on the specific role you apply for.
Stifel Financial Software Engineer candidate reports ↗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.
- 01Stifel Financial Software Engineer candidate reports ↗
Company-reported rounds, questions and FAQ.
Candidate reports · Accessed 2026-09-22 - 02PracHub Software Engineer practice ↗
PracHub practice material, not company-reported.
PracHub page · Accessed 2026-09-22 - 03PracHub preparation framework ↗
PracHub preparation guidance.
PracHub page · Accessed 2026-09-22