Interview guides · CG Advisor Network
CG Advisor Network Software Engineer Interview Guide
CG Advisor Network Software Engineer interview guide: 4 reported rounds, take-home test, OOP and C# questions, behavioral answers and a 7-day prep plan.
The 60-second brief
CG Advisor Network builds software for financial advisors and their clients, according to candidate reports. The work centres on managing financial data and on the interactions between an advisor and a client. Candidates describe the Software Engineer role as turning business requirements into maintainable code across backend services, interface design or full-stack features. The stack they mention is C#, JavaScript and CSS, with HTML among the web fundamentals. Some candidates describe a relaxed, professional working environment.
This guide is for candidates interviewing for a Software Engineer position at CG Advisor Network. It covers the four reported rounds (Recruiter Screening, Technical Assessment, Technical Interviews, Behavioral Interviews), the OOP, class-design and testing questions candidates report, and the experience questions, with an answer structure for each of those. It closes with a seven-day plan built around the C#, JavaScript and web fundamentals the role lists.
Candidates report four rounds over roughly 3-5 weeks: a recruiter screening, a take-home programming test, technical interviews and behavioral interviews. The reported questions lean on OOP fundamentals, class design, testing and discussion of your past projects.
Focus areas
- Coding interviews
- Technical interviews
- Object-Oriented Programming (OOP)
Overview
The reported technical questions are fundamentals. Four are conceptual engineering questions: the four pillars of OOP, the differences between public, protected and private access modifiers, how you design a class structure for a new feature, and how you test code to make sure it is reliable. A fifth, how you handle design patterns in daily work, is technical in subject even though it travels with the experience questions. Preparing for these means being able to put every concept into a short piece of code in C# or whichever object-oriented language you use, not reciting definitions.
The role description candidates describe lists OOP design, C# or a similar object-oriented language, and web fundamentals (HTML, CSS, JavaScript) as must-haves. Familiarity with financial technology, agile methods and automated testing frameworks appears as nice-to-have. Handling asynchronous operations in C# or JavaScript is listed among the advanced topics, so refresh async/await in C# and promises or async functions in JavaScript alongside the OOP basics.
Candidates also report that the loop includes a take-home programming test, whiteboarding sessions (in person or virtual), and in some cases a request to bring your own code to walk through. That makes your own projects part of the preparation: choose one you can explain decision by decision, and be ready to say what you would change. Meetings are reported to span peers, technical leads, hiring managers and department managers, so rehearse explaining the same project at different levels of detail.
The five experience questions (motivation for the company, a complex project, feedback on your code, what you want from a team, learning something new under a deadline) reward specific stories over general statements. The guidance on each question below gives a structure; what makes it work is real detail from your own history, including a number or an outcome you can stand behind.
The CG Advisor Network interview process
These are the four stages candidates report, in the order they describe them. The loop is described as straightforward overall, with intensity that varies by team.
Recruiter Screening
Candidates report a first call with a recruiter to check basic qualifications and fit for the role. Treat it as your first chance to explain your background in terms of the role: object-oriented work in C# or a similar language, web front-end fundamentals, and any financial or data-heavy software you have touched. The question about why you want a position at CG Advisor Network can come up this early or later, so have it ready.
What to demonstrate
- Whether your background matches the role's listed requirements: OOP design, C# or a similar language, HTML/CSS/JavaScript
- Basic fit for the role as candidates describe this screening
- How clearly you summarise your own experience
How to prepare
- Write a short walkthrough of your career that ends at this role, naming the languages and web technologies you have used in production.
- Prepare your answer to why you are interested in CG Advisor Network, using what you can verify about financial advisor tooling and the C#/JavaScript stack.
- Prepare logistics: availability, location and process questions, including asking what format the take-home test takes.
Technical Assessment
Candidates report a take-home programming test used to verify foundational coding skills. Reports also advise that the submission may be reviewed in detail later, so write it as code a colleague would be comfortable reading. The coding stage is where OOP structure, naming, decomposition and testing show up in files, not in conversation.
What to demonstrate
- Working, runnable code that covers the stated requirements
- Clean, readable structure that follows object-oriented principles
- Tests and edge-case handling in the submission
How to prepare
- Practise building a small program with a clear class structure, a separation between logic and input/output, and unit tests, in the language you would use for the take-home.
- Write a short README stating assumptions, how to run it and how to run the tests.
- Rehearse explaining your design choices out loud, starting with how you would structure classes for a new feature and how you decide what to test.
Technical Interviews
Candidates report a series of technical interviews with hiring managers and lead engineers. Reported formats include conceptual OOP questions, whiteboarding (in person or virtual) and, for some, a show-and-tell of code you bring. This is where the four pillars, access modifiers, class design, testing process and design patterns questions are practised.
What to demonstrate
- Command of OOP principles: inheritance, encapsulation, polymorphism and abstraction
- Understanding of access control (public, protected, private) and its effect on design
- Practical approach to design patterns, unit testing and asynchronous code in C# or JavaScript
How to prepare
- For each OOP pillar and access modifier, have a code example you can write on a whiteboard, with the reason it matters in a real design.
- Practise designing a class structure for a feature of your choosing, narrating as you draw: responsibilities, relationships, which members are private, what gets tested.
- Choose the project you would bring for a code walkthrough and be able to justify each design decision, including a pattern you used and why.
Behavioral Interviews
Candidates report interviews that explore your experience and cultural alignment with the team. They describe meeting people at several levels, from peers to technical leads and department managers. The reported questions are about why you want the job, a complex project you have done, how you take code feedback, what you look for in a team and how you learn under deadline pressure.
What to demonstrate
- How you describe past project outcomes and your own contribution
- How you work with other engineers, including code review
- Fit with a team-based environment, as candidates describe the round
How to prepare
- Build a story bank of four or five real episodes: a complex project, a review disagreement, a learning sprint under a deadline, a team practice that worked.
- For each story, write the decision you made, the alternatives you rejected and the result.
- Prepare two or three questions about the team's stack and how engineers collaborate with product and technical leads.
Where candidates lose points
Reciting textbook definitions of encapsulation, inheritance, polymorphism and abstraction with no code
Attach a short example to each pillar, such as an abstract base class with two subclasses overriding one method, and say what the design would look like without it. Do the same for access modifiers, including C# internal.
Submitting a take-home that runs but lives in one large file with no tests
Split logic from input/output, give classes single responsibilities, add unit tests for the core rules and the edge cases, and include a README with your assumptions. Candidates report the code may be revisited in later interviews, so be able to defend every choice.
Naming design patterns without being able to say what they replaced or what they cost
Prepare two patterns you have really used, with the code before and after. Be ready to say when a plain function or interface is the better choice.
Being unable to explain a project on your own resume, or describing it only in 'we' terms
Before each round, reread every project you listed. For the one you will present, write the architecture, your decisions, the trade-offs and what you would change.
Giving a generic answer to why you want the job, or guessing at a question you did not fully understand
Anchor your motivation in the financial advisor platform, the stack and the role's scope. When a question is unclear, restate it or ask a clarifying question before answering.
Questions & practice
Identify the heaviest tenants in a five-minute window under memory pressure
Medium · top-k · heavy hitters · streaming
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
- 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.
- 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.
- 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.
- 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?
Diff a projection against the primary without per-row point reads
Hard · reconciliation · range hashing · throttling
The listing projection has drifted and some rows show a stale version. The primary holds 40,000,000 resource rows across 12,000 tenants while serving 1,200 writes and 14,000 reads per second. The obvious repair, reading each resource row and comparing its version against the projection, is correct and would eventually finish. Explain precisely why it is unacceptable here, then give a diff that finds the differing rows, state its complexity, and make it safe to run against a live primary. Replication lag is usually under 100 ms and is not bounded.
Approach
- Quantify the naive cost rather than calling it slow: 40,000,000 point reads at even 0.5 ms each is over five hours serialised, and the only lever is concurrency, which is exactly what you cannot spend. The primary's pool is sized for the write path, and 40,000,000 random reads evict the buffer cache that sustains the 85 percent cache hit rate, so the audit degrades the system it is auditing.
- Replace random access with one ordered pass per side. Both sides can be read in (tenant_id, resource_id) order, which is a sequential scan on each and a merge join in O(n) time and O(1) memory. For a dense diff that is the whole answer, and it reads the primary once instead of 40,000,000 times.
- For the expected sparse case, compare range hashes instead of rows: partition the key space, compute per range an order-independent aggregate over hash(resource_id, version), compare aggregates, and descend only into ranges that differ. With d differing rows and branching factor B, at most d ranges mismatch per level, so the drill-down examines O(d log_B(n/d)) ranges and reads full rows only in mismatching leaves.
- Aggregate with a sum modulo 2^64 or a multiset hash, never XOR. XOR is order-independent but self-cancelling, so two rows wrong in the same way, or a row duplicated on one side, leave the range aggregate matching and the range is declared clean.
Follow-up
- The diff reports 900 stale rows. How do you decide between patching those rows and rebuilding the projection from resource_revision?
- Same job, but the projection lives in a search index that cannot be scanned in key order. What changes?
Canonicalise a request body into a stable idempotency fingerprint
Medium · parsing · canonicalisation · hashing
idempotency_key.request_fingerprint is a SHA-256 over the method, path and canonicalised body, and a retry whose fingerprint differs must be rejected with 422 rather than served the stored response. Write the canonicaliser. Bodies are JSON up to 256 KB nested at most 32 levels; clients vary key order, whitespace and unicode escaping, and some send 64-bit ids as JSON numbers. Produce a deterministic byte string such that semantically identical bodies match and any semantic difference does not. State your complexity and name two normalisations you refuse to perform.
Approach
- Parse once into a tree, then re-serialise under fixed rules: object keys sorted, array order preserved, one escaping convention, no insignificant whitespace. Parsing is O(n) and sorting keys is O(k log k) per object, so O(n log n) overall with O(depth) stack, and the 32-level cap is enforced during parsing because hostile nesting is how a canonicaliser becomes a stack overflow.
- Sort keys by their UTF-8 bytes and say why the obvious implementation is wrong in some runtimes: a default string comparison that orders by UTF-16 code units places surrogate pairs, meaning code points from U+10000 up, below U+E000 to U+FFFF, which is not UTF-8 byte order, so two services written in different languages disagree on the same document.
- Do not re-encode numbers through a double. IEEE-754 binary64 represents integers exactly only up to 2^53, so normalising a 19-digit id through a float changes it, and 1 against 1.0 cannot be reconciled without deciding whether they are the same value. Preserve the literal token, and require ids as strings at the API boundary if you want them comparable.
- Reject duplicate keys rather than picking one. JSON permits them and parsers disagree, most keeping the last, so any choice you make ties the fingerprint to a parser detail that the code handling the request does not necessarily share.
Follow-up
- A client sends the same logical request with an extra field your API ignores. Same key, different fingerprint, so you return 422. Is that the right answer?
- Where does the fingerprint get computed relative to request decompression and the body-size limit?
Keep soft-deleted accounts from blocking re-registration
Easy · soft delete · unique constraints · engine differences
app_user holds user_id, tenant_id, email CITEXT, password_hash (NULL for SSO principals), email_verified_at, auth_version, status ('invited','active','suspended','deactivated'), created_at, updated_at, deleted_at. Two live accounts for one address inside a tenant must be impossible, but an address freed by a soft delete must be reusable, and the same tenant may delete and re-register it repeatedly. Write the uniqueness DDL for PostgreSQL 16, then the equivalent for MySQL 8 where partial indexes do not exist, and say what each permits once three deleted rows already hold that address.
Approach
- Start from what is actually unique: not (tenant_id, email), but (tenant_id, email) among live rows. PostgreSQL says that directly — CREATE UNIQUE INDEX app_user_live_email ON app_user (tenant_id, email) WHERE deleted_at IS NULL. A full constraint over the same two columns burns the address permanently the first time someone deletes an account.
- Keep case-insensitivity in the type or the index, never in the application: CITEXT as given, or UNIQUE (tenant_id, lower(email)) as an expression index where the extension is unavailable. A case-sensitive unique column is exactly how two accounts for one human appear.
- For MySQL 8 the predicate has to move inside the key: add a discriminator column that is a constant 0 while the row is live and is set to user_id on delete, with UNIQUE (tenant_id, email, deleted_marker). Live rows share the constant and still collide; deleted rows differ from each other and stop colliding.
- State the NULL variant and its dependency: leaving the marker NULL for deleted rows also works, because a unique index treats NULLs as distinct — true in MySQL, and true in PostgreSQL only under the default NULLS DISTINCT, which PostgreSQL 15 lets you reverse. Check the polarity against the three existing deleted rows: constant-on-live is what preserves the collision you want, and reversing it silently admits duplicate live accounts.
Follow-up
- A deleted account re-registers with the same address the next day. Do the old resource rows follow the new user_id, and how does the API keep the two principals apart?
- How do you honour an erasure request while resource_revision.actor_user_id still references this table?
Find version gaps and relay lag with window functions
Medium · window functions · event tables · frame semantics
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?
Can you explain the four pillars of Object-Oriented Programming?
Medium · Technical and Object-Oriented Programmin
Approach
- Name all four and give each a one-line definition: encapsulation hides state behind a controlled surface, abstraction exposes what an object does but not how, inheritance reuses and specialises a base type, and polymorphism lets one call site run different implementations.
- Tie each one to C# syntax. Encapsulation is private fields behind properties or methods that guard invariants (a balance setter that rejects invalid values). Abstraction is an interface or abstract class. Inheritance is ': BaseClass'. Polymorphism is virtual/override, or an interface method resolved at runtime.
- Separate the kinds of polymorphism: runtime (subtype) polymorphism through virtual dispatch, compile-time polymorphism through method overloading, and parametric polymorphism through generics such as List<T>.
- State the limits: a C# class inherits from one class but can implement many interfaces. Deep hierarchies are brittle, so I prefer composition when the relationship is 'has-a' rather than 'is-a'.
- Finish with one small worked example that uses all four, for example an abstract Shape with an Area() override in Circle and Rectangle, called through a List<Shape>. That shows understanding beyond the textbook definitions.
Follow-up
- When would you choose an abstract class over an interface in C#, and how do default interface methods (C# 8+) change that choice?
- What is the difference between 'override' and 'new' on a method in a derived class, and what does each print when called through a base-type reference?
- Can you give an example where inheritance caused a problem and composition would have been better?
What are the differences between public, protected, and private access modifiers?
Medium · Technical and Object-Oriented Programmin
Approach
- Define the core three for class members: public is accessible from any code, private only inside the declaring type, and protected inside the declaring type and types derived from it.
- Add the rest of the C# set, since the question is likely asked in C#: internal (same assembly), protected internal (same assembly OR derived types), and private protected (derived types within the same assembly, C# 7.2+). Members default to private; top-level types default to internal.
- Mention the details that catch people out. C# private works at type level, so one instance can read another instance's private fields of the same class. A nested class can access its enclosing type's private members. From a derived class, a protected member can only be reached through an instance of the derived type, not through a base-type reference.
- Contrast with JavaScript: there is no protected keyword. Real privacy comes from #private class fields (ES2022) or closures. TypeScript's public/protected/private are checked only at compile time and erased at runtime.
- Explain the design reason: keep members as private as possible, expose behaviour through a small public surface, and treat protected as part of the API you promise to subclasses, because changing it breaks derived code.
Follow-up
- What is the difference between protected internal and private protected, and when would you use each?
- Why expose a property instead of a public field, if both look the same to the caller?
- How would you make a member visible to a unit test project without making it public (for example InternalsVisibleTo), and is that a good idea?
How do you approach designing a class structure for a new feature?
Medium · Technical and Object-Oriented Programmin
Approach
- Start from the requirement, not the classes: list the use cases, then pull out nouns (candidate entities and value objects) and verbs (candidate responsibilities and services). Confirm scope and what is likely to change before drawing anything.
- Give each class one reason to change (single responsibility). Keep domain logic separate from I/O: a pure domain class, a repository or gateway interface for persistence or external calls, and a thin controller or UI layer on top.
- Hide what varies behind an interface. For example, an INotificationSender with Email and Sms implementations, chosen by configuration or a factory. A new channel is then a new class, not an edited switch statement (open/closed).
- Prefer composition and constructor injection over inheritance: dependencies come in through the constructor as interfaces, which makes the class testable with fakes and lets a DI container wire it up. Use immutable value objects (records in C#) for data such as money amounts or date ranges.
- Name the trade-off: do not add interfaces or patterns for variation that does not exist yet (YAGNI). I sketch the minimal design, write a test against the public surface, and refactor when a second real case shows up.
Follow-up
- A new requirement adds a third variant with slightly different validation rules. What changes in your design, and what stays untouched?
- Where would you put validation: in the constructor, in a separate validator, or in the service layer, and why?
- How would you unit test the service class in your design without touching a real database or email server?
Can you explain your process for testing code to ensure reliability?
Medium · Technical and Object-Oriented Programmin
Approach
- Describe the layers and what each catches. Fast unit tests on pure logic (xUnit, NUnit or MSTest in C#; Jest or Vitest in JavaScript), integration tests for database, API and serialization boundaries, and a few end-to-end tests on the main user paths.
- Show how a unit test is built: Arrange-Act-Assert, one behaviour per test, names that state the scenario and expected result, and boundary cases on purpose: null, empty collections, zero and negative values, maximum sizes, and decimal rounding (decimal rather than double for money in C#).
- Explain how you isolate dependencies: code against interfaces and pass in fakes or mocks (for example Moq). Inject the clock (TimeProvider in .NET 8, or an IClock) instead of calling DateTime.Now. Avoid Thread.Sleep in tests so they stay deterministic.
- Cover async code: test methods return async Task, never async void. Await the call and assert on thrown exceptions with Assert.ThrowsAsync. In JavaScript, return or await the promise so the test cannot pass before the assertion runs.
- Close the loop: every bug fix ships with a regression test that fails before the fix. Tests run in CI on every pull request. Coverage is a signal for untested branches, not a target, and flaky tests are quarantined and fixed instead of retried.
Follow-up
- How would you test a method that depends on the current date or on a database call?
- What is the difference between a mock, a stub and a fake, and when would you avoid mocking altogether?
- A test passes locally but fails intermittently in CI. How do you track down the cause?
Listing latency scales with page size, not with filters
Easy · n+1 · latency · query batching
The tenant listing endpoint reads resource filtered by tenant_id and status, ordered by updated_at DESC, and returns each row plus the owner's display name from app_user and the actor of that resource's latest resource_revision. p99 is 55 ms at 10 rows per page and 1.4 s at 200. Database telemetry shows 401 statements per request, each under 1 ms, and nothing in the slow-query log. Diagnose the cause and give the fix, stating the statement count per request and the p99 you expect afterwards.
Approach
- Read the counters before forming a theory. 401 statements for 200 rows is one driver query plus two per row, and sub-millisecond execution with an empty slow-query log rules out a bad plan. The time is round trips, which is why it is invisible in every per-query metric and scales with rows returned rather than with filter selectivity.
- Name the two per-row statements from their normalised text: a single-row app_user lookup by user_id, and a resource_revision lookup by resource_id ordered by version DESC LIMIT 1. Confirm by dropping those two response fields and watching the statement count fall to one. That locates the calls in the serialisation layer, not the repository.
- Check that the arithmetic accounts for the whole gap. Measure one round trip to the replica in isolation; 400 trips at roughly 3 ms of network plus 0.2 ms of execution is about 1.3 s on top of a 55 ms baseline, which matches. If the multiplication had fallen short, the N+1 would only be part of the story and you would keep looking.
- Batch both lookups. Collect owner_user_ids and resource_ids from the driver query, then issue WHERE tenant_id = $1 AND user_id = ANY($2) for the users, and PostgreSQL's SELECT DISTINCT ON (resource_id) ... WHERE resource_id = ANY($2) ORDER BY resource_id, version DESC for the latest revision, which the UNIQUE (resource_id, version) index serves directly. On an engine without DISTINCT ON, use a lateral join or a row_number window. Three statements per request at any page size.
Follow-up
- The page size is capped at 200 today. What breaks first if it is raised to 2,000, and is it still this bug?
- How do you stop the next N+1 from reaching production, given that no individual query is slow and the endpoint's tests pass?
Suggested practice checklist
The plan follows the four reported rounds: day one maps the loop, days two to five cover OOP, class design, testing, the take-home and whiteboarding, and days six and seven cover the experience questions and a full mock.
Day 1 — Map the loop and audit your fundamentals
- Write the four reported rounds and, beside each, the questions from this guide it is likely to include.
- Rate yourself on C# (or your main language), JavaScript, HTML/CSS, async programming and unit testing, and mark the weakest two.
- List every project on your resume and mark the one you would walk through in detail.
Deliverable: A one-page loop map, a skills rating with the two weakest areas marked, and a chosen project for walkthroughs.
Day 2 — OOP pillars and access modifiers in code
- Write a small class hierarchy that shows inheritance, encapsulation, polymorphism and abstraction, each labelled with the line that demonstrates it.
- Write a table of public, protected, private and, if you use C#, internal, with one reason you would choose each.
- Answer both conceptual questions aloud, using your code as the example.
Deliverable: One annotated code file showing the four pillars, a one-page access modifier table and recorded spoken answers.
Day 3 — Class design and design patterns
- Pick a feature, for example a calculation with several interchangeable rules, and sketch its classes, relationships and which members are private.
- Refactor a conditional-heavy version into a Strategy or Factory design and write down what got easier and what got harder.
- Prepare your answer on design patterns you use day to day, with two real examples and one case where you chose not to use a pattern.
Deliverable: A class diagram, a before-and-after refactor and a spoken answer on design patterns.
Day 4 — Testing and a take-home style build
- Build a small program with unit tests that cover normal cases, boundary values and invalid input, and a README with assumptions.
- Add one asynchronous operation (an async call in C# or JavaScript) and test it, including a failure path.
- Write your testing process as a short spoken answer: what you test first, what you mock and what you leave for integration tests.
Deliverable: A tested mini project with a README and a spoken answer on how you test for reliability.
Day 5 — Whiteboard and web fundamentals
- Redo the class design from day three on paper or a whiteboard, narrating each decision aloud.
- Review HTML, CSS and JavaScript basics: DOM events, CSS layout, promises and async functions, and the C# async/await equivalents.
- Pick the code you would bring to a show-and-tell and write a one-page explanation of each design decision.
Deliverable: A narrated whiteboard run-through and a one-page walkthrough of your showcase project.
Day 6 — Build your story bank for the experience questions
- Write a structured story for the complex project, the code feedback question and the learning-under-deadline question, each with decision, alternatives and result.
- Write your answer on why CG Advisor Network, using verifiable facts about the platform and the stack, and your answer on what you want from a team.
- Say each answer aloud and cut anything that does not carry a specific detail.
Deliverable: Five written story outlines and spoken versions of each.
Day 7 — Full mock and questions to ask
- Run a full mock: a recruiter-style introduction, two conceptual OOP questions, a whiteboard class design and two experience questions.
- Review where you hesitated and fix the weakest answer.
- Write two or three questions about the team's stack and how engineers work with product and technical leads.
Deliverable: A completed mock, a fixed weakest answer and a list of questions to ask.
Experience and team-fit preparation
The behavioral stage is reported to cover your experience and fit with the team. The reported questions span motivation for the company, a complex past project, code feedback, what you want from a team and learning under a deadline. For a Software Engineer, the strongest stories show your technical decisions, how you work with reviewers and technical leads, and a result you can check.
How do you handle design patterns in your daily development work?
Medium · Technical and Object-Oriented Programmin
Approach
- Name two or three patterns you have really used and the problem each solved. Examples: Strategy to replace a growing switch on type (such as rule-based calculations), Factory to centralise object creation, Repository to separate data access, Observer or events for notifications, and dependency injection to wire these together in C#.
- Tell it as problem, pattern, result: the code was a long conditional, I extracted an interface with one class per case, and adding a new case became a new class plus a test rather than an edit to shared code.
- Say when you do not reach for a pattern. A pattern added before a second variant exists is indirection with no payoff, and in C# or JavaScript a delegate or plain function often replaces a whole class hierarchy.
- Mention the costs honestly: more files, harder navigation, and the need for the team to recognise the pattern. Naming classes after the pattern (OrderPricingStrategy) makes review easier.
- Have one example in each language you list: an interface plus constructor injection in C#, and a module or factory function in JavaScript.
Follow-up
- What is the difference between Strategy and State, given that both swap behaviour behind an interface?
- How would you refactor a 200-line method that switches on a type code?
- Why do people criticise Singleton, and how does it affect unit testing?
Why are you interested in a position at CG Advisor Network?
Medium · Behavioral and Experience-Based
Approach
- Build the answer from what you can verify: the company builds platforms for financial advisors and their clients, handles financial data, and uses C#, JavaScript and CSS. Say which of those connects to your work, with one concrete project.
- Use three parts: what about the domain interests you (software where correctness and data handling matter to professionals), what you bring (a specific project), and what you want to do in the role (backend services, interface design or full-stack features).
- Do your own research before the call and quote something specific you found, such as a product page or the job posting. Do not assert things about the company's culture or strategy that you cannot support.
- If you have no fintech background, which is listed as nice-to-have, say what transfers: precise handling of money-like values (decimal types rather than floating point), audit trails, and permission-sensitive data.
- Keep money, commute and a generic wish to grow out of the lead reason; they do not tell the interviewer anything about the role.
Follow-up
- What do you know about the product and who uses it?
- Would you rather work on backend services, the interface or both, and why?
- What would make you choose this role over another offer?
Can you walk me through a complex project you’ve worked on in the past?
Medium · Behavioral and Experience-Based
Approach
- Pick a project listed on your resume, because candidates are told to expect specific questions about those projects. Choose one where you owned decisions, not one you only watched.
- Open with one sentence of context, then describe the architecture aloud as if sketching it: components, data flow, languages and where state lives. Be ready to draw it on a whiteboard.
- Say what made it complex (ambiguous requirements, integration with other systems, legacy code, data volume) and the hardest technical problem. Name two options you weighed and the trade-off that decided it.
- Cover how you tested and released it, and end with an outcome you can verify. Use a number only if it is real.
- Separate your own contribution from the team's. Narrating everything in 'we' leaves the listener unable to tell what you did.
Follow-up
- What was the biggest technical risk, and how did you reduce it?
- What would you change if you rebuilt it today?
- How did you test it, and what bug did the tests miss?
How do you handle feedback on your code from other engineers?
Medium · Behavioral and Experience-Based
Approach
- Tell one specific review: the comment, what you first thought, and how you checked it. Separate matters of taste from matters of correctness, and where unsure, reproduce the issue with a test before replying.
- Show the full loop: you read the feedback, asked a clarifying question if the intent was unclear, made the change or pushed back with evidence, and followed up.
- Include a case where feedback improved the code, such as a missed null case or a naming problem you adopted a convention for afterwards, and say what you changed in how you write code.
- Show the other side: you also review, keep pull requests small and describe why a change is made, so feedback is about the code.
- Avoid claiming you never get pushback or that you accept every comment without thought; both read as unexamined.
Follow-up
- Describe a time you disagreed with a more senior engineer's review comment. What happened?
- How do you give review feedback to a teammate?
- What do you do when a reviewer's comments conflict with the team's existing style?
What do you look for in a team-based development environment?
Medium · Behavioral and Experience-Based
Approach
- This is a values question, so back each value with evidence. Pick three or four working practices: a code review culture, automated tests running before merge, clear ownership of components, and accessible technical leads, then tie each to a time it helped you.
- Link to what candidates report about the role: engineers work with technical leads and product managers, give status updates and take part in peer code reviews. Say what you need from that setup, such as a way to clarify requirements quickly.
- Include one lesson from an environment that lacked something, such as no tests or unclear ownership, and what you did about it without blaming people.
- Avoid answers that list perks or say 'good culture'. Be concrete about how you work best, including when you want to work independently and when you want to pair.
Follow-up
- Tell me about a team environment that did not work for you, and what you changed.
- How do you work when requirements are unclear and the product manager is unavailable?
- How do you keep communication clear in a team that is partly remote?
Describe a time you had to learn a new technology or tool under a deadline.
Medium · Behavioral and Experience-Based
Approach
- Use a STAR structure with the time pressure explicit: what technology or tool, why the project needed it, and what the deadline put at stake. Choose a real technology related to this role, such as a testing framework, async programming in C# or JavaScript, or a front-end library.
- Describe your learning method: scoping to the smallest slice you needed, reading the official documentation, building a throwaway spike first, and asking someone with experience or pairing with them.
- Explain how you managed risk: what you cut, how you tested the unfamiliar parts, and how you told the team where you were and what remained uncertain.
- Close with the result and what stuck: the cleanup you did after delivery, a note you wrote for the team, or a gap you closed later.
- Avoid saying you mastered it in a few days. Credibility comes from naming what you did not know and how you contained it.
Follow-up
- What did you get wrong the first time?
- How did you decide you knew enough to ship?
- Would you approach the same deadline differently now?