CONTENTS

    My 2025 Trade Desk CodeSignal Interview Experience and Questions

    avatar
    Silvia AN
    ·November 14, 2025
    ·13 min read
    My firsthand Trade Desk CodeSignal interview experience and key takeaways

    I took The Trade Desk's CodeSignal assessment not long ago. The assessment lasted 90 minutes in total, and each level’s specific coding section could only be unlocked after passing the previous level. Below, I will share the questions for each level as well as my detailed problem-solving approach at the time.

    I genuinely appreciate how much Linkjob.ai has helped me throughout the process, which is why I’m sharing all of my OA details here. Having an invisible AI assistant running in the background really takes away a lot of stress.

    My Trade Desk CodeSignal Interview Questions

    Level 1: Implementation of Core Transaction Functions

    Requirement Breakdown

    Three fundamental functions (account creation, fund deposit, and fund transfer) needed to be implemented, with clear return values and core validation logic to ensure accurate data flow and no anomalies:

    • CreateAccount(timestamp: int, accountId: str) -> bool success: Creates a new account. Returns true if creation is successful, and false if the accountId already exists (to avoid duplicate accounts).

    • DepositMoney(timestamp: int, accountId: str, amount: int) -> int balance: Deposits a positive integer amount into the specified account. First verifies the existence of the account; after deposition, returns the updated balance.

    • TransferMoney(timestamp: int, source: str, target: str, amount: int) -> int balance: Transfers funds from the source account to the target account. Requires verification that both accounts exist and the source account has a balance ≥ the transfer amount. After the transfer, returns the updated balance of the source account (supplementing return value details). Meanwhile, the outgoing amount of the source account must be recorded (to reserve data for the "total expenditure statistics" in Level 2).

    Key Implementation Ideas

    Data Structure Selection: Use a hash table (e.g., Python’s dict) as the core storage. The key is accountId, and the value is a dictionary containing multiple fields. Example structure:

    
    accounts = {
    "account123": {
    "balance": 0, # Current balance
    "total_outgoing": 0, # Cumulative expenditure (transfer-out + subsequent withdrawals), used in Level 2
    "transactions": [], # Transaction records (including timestamp, type, amount, etc.), used for merging in Level 4
    "is_merged": False, # Flag indicating if the account has been merged, used for queries in Level 4
    "merged_to": None # If merged, records the target account ID, used for queries in Level 4
    }
    }

    Boundary and Exception Handling:

    • Before all operations, verify if the account exists. If CreateAccount is called with an existing ID, return false; if Deposit or Transfer is called with a non-existent ID, throw an exception or return an error indicator (per interview agreement).

    • Amount validation: The amount for Deposit and Transfer must be a positive integer; otherwise, the operation is rejected.

    • Special transfer validation: The source and target accounts cannot be the same (to avoid invalid operations), and the source account’s balance must be ≥ the amount to prevent overdrafts.

    Level 2: Top K Accounts by Total Expenditure

    Requirement Upgrade

    On the basis of Level 1, add the WithdrawMoney interface and implement the "Top K accounts by total expenditure" function:

    New Interface: WithdrawMoney(timestamp: int, accountId: str, amount: int) -> int balance: Withdraws funds from the specified account. Requires verification that the account exists and the balance ≥ the withdrawal amount. After withdrawal, returns the updated balance, and the withdrawal amount is included in "total expenditure".

    Top K Query Rules:

    • Definition of total expenditure: The sum of the account’s Transfer outgoing amount and Withdraw amount (i.e., the accumulated value of the total_outgoing field).

    • Sorting logic: First sort by total expenditure in descending order; if amounts are equal, sort by accountId in ascending alphabetical order.

    • Return format: A list where each element is (accountId, totalSpend), e.g., [("acc001", 5000), ("acc002", 3000)] (supplementing a specific format example).

    Key Implementation Ideas

    Cumulative Logic for Total Expenditure: When TransferMoney (for the source account) and WithdrawMoney are executed, synchronously update accounts[accountId]["total_outgoing"] to avoid traversing historical records during subsequent statistics (improving efficiency).

    Efficient Calculation of Top K:

    • If the number of accounts is small (e.g., in the simplified scenario of an interview), directly traverse all unmerged accounts (excluding accounts with is_merged=True), collect (accountId, total_outgoing), sort them according to the rules, and take the top K.

    • For performance considerations, maintain a priority queue (min-heap) with a size of K. Dynamically replace the top element of the heap during traversal; the final elements in the heap are the Top K (note that when amounts are equal, the accountId must be included in the heap elements for comparison to handle ascending sorting).

    Boundary Handling: Determine whether accounts with zero total expenditure should participate in sorting (per interview agreement, usually only accounts with expenditure are counted). If K is larger than the total number of accounts, return all eligible accounts.

    I have to say, Linkjob AI is really easy to use. I used it during the interview after testing its undetectable feature with a friend beforehand. With just a click of the screenshot button, the AI provided detailed solution frameworks and complete code answers for the coding problems on my screen. I’ve successfully passed the test, with the HackerRank platform not detecting me at all.

    Level 3: Scheduled Payments and Status Query

    Requirement Breakdown

    Implement "scheduled payment" and "cancel payment" functions, while supporting queries on the execution status of scheduled payments. Core rules are supplemented as follows:

    Scheduled Payment Interface: SchedulePayment(timestamp: int, accountId: str, amount: int, timeDelay: int) -> str paymentId:

    • Function: Automatically deduct the amount from the accountId at current timestamp + timeDelay (this amount must be included in the account’s "total expenditure").

    • paymentId Generation Rule: Share a global auto-increment counter, formatted as "payment$counter" (e.g., if the counter starts at 1, the paymentId for the first scheduled payment is "payment1").

    • Pre-verification: Confirm that the account exists and the amount is a positive integer; there is no need to verify the current balance (verification will be done when the payment is executed).

    Cancel Payment Interface: CancelPayment(timestamp: int, accountId: str, paymentId: str) -> bool success:

    • Function: Cancel the specified scheduled payment. Cancellation is only allowed if "the payment has not been executed" (i.e., current timestamp < scheduled execution time).

    • Return Value: true indicates successful cancellation; false indicates failed cancellation (e.g., paymentId does not exist, account mismatch, payment has been executed or cancelled).

    New Status Query Interface: GetStatus(timestamp: int, accountId: str, paymentId: str) -> str status:

    • Function: Query the status of the specified scheduled payment. Return values include "SCHEDULED" (scheduled but not executed), "EXECUTED" (executed), "CANCELLED" (cancelled), and "FAILED" (execution failed, e.g., insufficient balance).

    • Verification: Confirm that the paymentId belongs to the current accountId; otherwise, return an error status (e.g., "INVALID_ACCOUNT").

    Key Implementation Ideas

    Storage Structure for Scheduled Payments: Add a hash table schedule_payments, where the key is paymentId and the value is a dictionary containing the following fields:

    
    schedule_payments = {
    "payment1": {
    "accountId": "acc001",
    "amount": 1000,
    "scheduled_time": 1620000000, # timestamp + timeDelay
    "status": "SCHEDULED", # Initial status
    "create_timestamp": 1619999000 # Timestamp when the scheduled payment was created
    }
    }

    Meanwhile, maintain a global auto-increment counter payment_counter (initialized to 0). Each time SchedulePayment is called, counter += 1 to generate the paymentId.

    Payment Execution Logic: Maintain a "pending payment list", sorted in ascending order of scheduled_time. Each time an operation (e.g., Deposit, Transfer) or query is performed, first check if there are payments in the list with scheduled_time ≤ current timestamp:

    • During execution, verify the account balance: If the balance ≥ amount, deduct the amount, update the account balance and total_outgoing, and change the status to "EXECUTED".

    • If the balance is insufficient, change the status to "FAILED" (no repeated execution to avoid repeated deductions).

    Cancel Payment Logic: Query the record corresponding to paymentId in schedule_payments. Verify that the accountId matches, the status is "SCHEDULED", and the current timestamp < scheduled_time. If all conditions are met, change the status to "CANCELLED" and return true.

    Level 4: Account Merging and Historical Balance Query

    Requirement Breakdown

    Implement the account merging function (retaining balances and transaction records) and support historical balance queries. Core rules are supplemented as follows:

    Account Merging Interface: Merge(timestamp: int, source: str, target: str) -> bool success:

    • Function: Merge the source account (source account) into the target account (target account). After merging, the source account can no longer be operated (marked as merged).

    • Merged Content: Add the current balance of the source account to the target account’s balance, add the source account’s total_outgoing to the target account’s total_outgoing, and append the source account’s transaction records to the target account’s transaction records.

    • Pre-verification: Both source and target accounts exist, neither has been merged (to avoid repeated merging), and sourcetarget. If all conditions are met, return true.

    Historical Balance Query Interface: GetBalance(int requestExecutionTime, string accountId, string queryTime) -> int balance:

    • Function: At the requestExecutionTime, query the balance of the accountId at queryTime (which needs to be converted to an integer timestamp).

    • Key Restriction: If accountId is a merged account (source account) and queryTime ≥ the timestamp of merging, return a null value or 0 (clarifying the rule that "querying historical balances after merging returns null"). If queryTime < merging time, query the historical balance of the source account before merging.

    Key Implementation Ideas

    Data Processing for Account Merging:

    • During merging, update the balance, total_outgoing, and transactions of the target account (directly extend the transaction records of the source account).

    • Mark the source account with is_merged=True and merged_to=target. All subsequent operations (e.g., Deposit, Transfer) on the source account will return failure.

    • Handle pending scheduled payments of the source account: If there are paymentIds with status "SCHEDULED", choose to either cancel them automatically (change status to "CANCELLED") or transfer them to the target account (update the accountId of the payment). Select the option per interview agreement; cancellation is usually simpler.

    Historical Balance Query Logic:

    • First, verify the account status: If accountId is a merged source account and queryTime ≥ merging timestamp, return null.

    • If the account is valid, traverse the transactions list of the account (transaction records must include fields such as timestamp, type, amount, and balance_after). Find the last transaction with timestamp ≤ queryTime; its balance_after is the balance at queryTime.

    • Optimization: Maintain "historical balance snapshots" in transaction records to avoid traversing all records during each query (e.g., save a snapshot every 10 transactions to reduce the number of traversals).

    Trade Desk CodeSignal Test Experience

    Before the interview, I also came across a set of highly valuable real interview questions. I'm attaching them here for reference.

    Level 1: Basic Functions

    Core Req

    Basic key-value DB (DB: {key: {field: value}}); all interfaces take timestamp (no clear use in Level 1).

    Interfaces

    1. set(timestamp: int, key: str, field: str, value: int)
      Set value for field under key; create key if missing, overwrite field if exists.

    2. get(timestamp: int, key: str, field: str) -> int | None
      Query field value under key; return None if key/field missing.

    3. compare_and_set(timestamp: int, key: str, field: str, expected_value: int, new_value: int) -> bool
      Update to new_value if field == expected_value (return True); else False (key/field missing or mismatch).

    4. compare_and_delete(timestamp: int, key: str, field: str, expected_value: int) -> bool
      Delete field if value == expected_value (return True); else False (key/field missing or mismatch).

    Level 2: Scan Functions

    Core Req

    Add full scan by key and prefix-filtered scan (based on Level 1).

    Interfaces

    1. scan(timestamp: int, key: str) -> list[str]
      Return [field(value)] for all fields under key; empty list if key missing.

    2. scan_with_prefix(timestamp: int, key: str, prefix: str) -> list[str]
      Return [field(value)] (strings start with prefix) under key; empty list if key missing/no match.

    Level 3: TTL Support

    Core Req

    Add TTL-enabled set interfaces; adapt existing interfaces to ignore expired fields.

    Implementation

    1. Data Structure
      Upgrade to DB: {key: {field: {value: int, expire_at: int}}} (expire_at = timestamp + ttl; ttl=0 → never expire).

    2. New Interfaces

    • set_with_ttl(timestamp: int, key: str, field: str, value: int, ttl: int)
      Set value + expire_at for field (same logic as set).

    • compare_and_set_with_ttl(timestamp: int, key: str, field: str, expected_value: int, new_value: int, ttl: int) -> bool
      Same as compare_and_set; set expire_at if update succeeds.

    1. Existing Interfaces Adaptation
      For set/get/compare_and_set/compare_and_delete/scan/scan_with_prefix: if field exists and expire_at > 0 && timestamp > expire_at → treat as non-existent.

    Level 4: Historical Query

    Core Req

    Add interface to query value valid at a specified historical time.

    Implementation

    1. Data Structure
      Add HistoryDB: {key: {field: list[{value: int, set_at: int, expire_at: int}]}} (record each field change; original DB = latest state cache).

    2. New Interface
      get_when(timestamp: int, key: str, field: str, at_timestamp: int) -> int | None

    • Traverse field’s history; filter latest record (set_at <= at_timestamp and (expire_at == 0 || expire_at > at_timestamp)).

    • Return value if record exists; else None.

    1. Adaptation
      All Level 1-3 write ops (set/compare_and_set/set_with_ttl/compare_and_set_with_ttl) sync to HistoryDB.

    Trade Desk CodeSignal OA Summary and Core Assessment Focuses

    Data Structure Selection Ability

    The rational use of hash tables (for account storage and scheduled payment storage), priority queues (for Top K), and lists (for transaction records and pending payments). It is necessary to explain the reasons for selection (e.g., hash tables support O(1) lookup and modification, making them suitable for high-frequency account operations).

    Logical Integrity

    Pre-verification (account existence, valid amount, valid status) and post-data synchronization (balance, total expenditure, transaction records) for each interface. Both "normal processes" and "abnormal scenarios" (e.g., insufficient balance for transfers, cancelling executed payments) need to be covered.

    Scalability Considerations

    When adding functions from Level 1 to Level 4, it is necessary to ensure that new functions do not break existing logic (e.g., scheduled payments in Level 3 do not affect total expenditure statistics in Level 2, and merging in Level 4 does not affect historical queries). Data field design should reserve space for expansion (e.g., is_merged and merged_to fields).

    Detail Handling

    Details such as the generation rule of paymentId, the implementation of alphabetical sorting for accountId (needing to call string comparison methods), and the handling of scheduled payments after merging. These details reflect the rigor of the code.

    My Preparation Strategy for The Trade Desk CodeSignal

    Platform Familiarity

    Before starting practice problems, I spent time familiarizing myself with the testing environment. I registered for a CodeSignal account and used its Practice Area. This helped me adapt to the IDE layout, keyboard shortcuts, and the process of running test cases.

    I also conducted mock assessments. This was crucial for training myself to remain focused under real-time pressure. During these simulations, I strictly adhered to the test rules, avoiding external resources to eliminate test anxiety.

    Core Algorithms and Data Structures (My Study Focus)

    I knew the CodeSignal assessment usually consisted of four questions of varying difficulty, so my study was highly structured and focused on Medium-difficulty problems.

    My study plan covered these key areas:

    Arrays and Strings: I focused on two pointers, sliding window techniques, and hash maps, practicing problems involving substring searches, deduplication, and ordered array operations.

    Linked Lists: I focused on fundamental operations like fast and slow pointers, reversal, and merging.

    Trees and Graphs: I practiced Depth First Search (DFS) and Breadth First Search (BFS), covering traversal problems and connected components.

    Efficiency Optimization: I emphasized binary search, dynamic programming, and greedy algorithms, focusing on problems where an O(N log N) or O(N) solution was necessary.

    My practice method was disciplined. I did not just blindly solve problems; I dedicated two to three days to each data structure or algorithm type to ensure I thoroughly understood the underlying principles and optimal solution patterns. I also set strict time limits for myself during daily practice (e.g., 15-20 minutes for a medium problem) to train my ability to think and make quick decisions.

    Code Quality and Performance

    I understood that The Trade Desk highly valued code efficiency, readability, and engineering standards. I made sure my code met a high standard. I always analyzed the time and space complexity of the problem before writing any code. If my initial idea was O(N squared), I worked hard to find an O(N) or O(N log N) solution. My code was clean; I used clear variable and function names. Especially for the third, more extensive implementation question, I split complex logic into multiple functions with single responsibilities to ensure high readability and maintainability. I proactively considered and tested edge cases, including null inputs, invalid inputs, and boundary conditions, to ensure my code ran robustly.

    FAQ

    Can I skip questions and come back later?

    If you’re referring to skipping a certain level, that’s not possible. The four levels of questions follow a sequential order. You can’t unlock subsequent levels without completing the previous ones. However, you can first check the requirements for the later levels to get an overall understanding before starting to write code.

    What core tech topics are tested in Trade Desk/Signal coding interviews?

    Focus on low-latency systems: efficient key-value stores, LRU/LFU caches, binary search, and O(1)/O(log n) optimized algorithms for real-time data processing.

    See Also

    Sharing My Authentic Experience With xAI CodeSignal Assessment

    My Journey to Success in Hudson River Trading Assessment

    Successfully Overcoming the Meta CodeSignal Test Experience

    Lessons Learned From My Visa CodeSignal Assessment Journey

    My Insider Tips for Passing the Coinbase CodeSignal Assessment