cswork / libraryOpen practice workspace

Interview guides · Cojali S. L.

Cojali S. L. Software Engineer Interview Guide

Cojali S. L. Software Engineer interview guide: two reported rounds, electronics and embedded questions, debugging, STAR stories and a 7-day plan.

The 60-second brief

Candidates describe Cojali S. L. as a company that sits between automotive hardware and software. The products named are diagnostic tools, fleet management platforms and connectivity solutions, which clients use to maintain vehicles and run their operations. A Software Engineer is described as working across the development lifecycle, from design through deployment and maintenance, building the backend services and applications behind the diagnostic tools and working regularly with hardware engineers on the point where physical devices meet software interfaces.

This guide is for Software Engineer candidates preparing for the Cojali S. L. loop. It covers the two reported rounds, the eight reported questions (four on electronics, debugging and low-level work, four on career history and motivation), and the review areas candidates list: system architecture, code quality and debugging method. It also includes a seven-day plan, behavioral stories to rehearse and answers to the process questions candidates ask most.

Candidates report two rounds over roughly 2-4 weeks: a Professional Background Review, then Technical Assessments focused on practical engineering skills. Interviews may run in English or Spanish depending on the team.

Focus areas

  • Python
  • LLMs (Large Language Models)
  • AI Agents (Agentic Systems)

Overview

The reported questions for this role split into two groups. The first group sits on the boundary between electronics and software: how circuits interface with code, how to debug when the fault could be on either side, experience with embedded or low-level programming, and a story about optimizing code under tight resource limits. The second group is career history and motivation: your background and most complex project, why this company, how you trade delivery speed against maintainable code, and where you want to go. None of the reported questions is an algorithm puzzle, so the preparation is mostly about explaining real work precisely.

Candidates also report two example scenarios for the technical stage: walking through a technical challenge you solved using electronics knowledge or software patterns, and designing a software component that talks to a new hardware sensor. For the sensor question, practise an outline you can say aloud: a narrow interface that hides the device, an adapter that owns timing and parsing, explicit handling for missing, late or corrupt readings, a simulator or recorded-data replay so the logic can be tested without the board, and a clear place for calibration and unit conversion.

The requirements candidates describe list C++, Python or C# as the core languages, plus software architecture and version control. Embedded systems, automotive diagnostic protocols and Agile experience are listed as nice-to-have. Topic tags attached to reports also include Python, web backend development and scalability, so keep one backend refresher in your plan: a service you can describe end to end, how it is tested, and how it would behave under more load. Be ready to justify language and framework choices on performance, scalability and maintainability, and to discuss pros and cons of every technology on your CV.

Finally, plan for language. Candidates report that parts of the process can be in English and parts in Spanish, so rehearse your project stories and your technical vocabulary (interrupt, buffer, sampling rate, regression, rollback) in both. Salary expectations are reported to be worth stating clearly at the initial HR screening, and some candidates note that pay growth can be limited, so decide your position before the first call.

The Cojali S. L. interview process

Candidates report two rounds over roughly 2-4 weeks. The descriptions below are what candidates say about each stage, plus how to prepare for it; the order is the reported one.

Professional Background Review

Candidates describe the first stage as an initial conversation about your professional background and experiences. One report calls it a phone screen, and salary expectations are reported to come up at the initial HR screening. A background conversation is where career-history questions are practised, and the reported ones of that type ask about your most complex project, why this company, balancing delivery speed with maintainable code, and your long-term goals. Approach it as a guided tour of your CV: a short narrative of your path, one project you can take apart in detail, and a clear reason for choosing this company that names the diagnostic, fleet management or connectivity products.

What to demonstrate

  • Your account of your own career and the projects on your CV
  • Whether you can go deep on any technology you list, including its pros and cons
  • How clearly you explain a decision and its trade-off, in English or Spanish as the team requires

How to prepare

  • Write a two-minute background narrative and a longer version of your most complex project: your role, the architecture, two decisions you made and the outcome
  • For every technology on your CV, write one strength, one weakness and one situation where you would not choose it
  • Prepare a company answer that names the reported product areas (diagnostic tools, fleet management platforms, connectivity) and links one of them to your own experience
  • Decide your salary expectation and say it aloud in both English and Spanish

Technical Assessments

Candidates describe the second stage as deeper technical assessments on practical engineering skills. The format (live coding, take-home, whiteboard or panel) is not reported, so prepare to explain and reason out loud rather than assume one. The reported fundamentals questions cover circuits and how they interface with software, debugging when the fault could be software or hardware, embedded or low-level experience, and optimizing code under resource limits. Candidates also list system architecture, code quality (testing, documentation, version control) and debugging method as the areas to review, and give two example scenarios: a challenge solved with electronics or software patterns, and a software component for a new hardware sensor.

What to demonstrate

  • Practical engineering skills, as the stage is described
  • Hardware-software fundamentals: circuits, embedded and low-level work
  • A systematic debugging approach across the software-hardware boundary
  • Architecture and code-quality reasoning for a component that touches hardware

How to prepare

  • Trace one signal end to end on paper: sensor voltage, conversion, sampling, bus or interface, driver, parsing, units, application logic
  • Write a debugging checklist for a fault that could be either side: reproduce, swap a known-good part, log at the boundary, replay recorded input into the software
  • Outline the sensor-component design: interface, adapter, error and timeout states, simulator, calibration and tests
  • Refresh your strongest language from C++, Python or C#, and prepare to explain how you test and version the code you write

Where candidates lose points

Reciting circuit theory with no link to software

Prepare one traced signal path from sensor to application variable (conversion, sampling, bus, driver, parsing, units). Explain each hand-off in terms of what code has to do there, such as debouncing, timeouts or scaling.

Answering the software-or-hardware debugging question by guessing a side or jumping to a fix

Give a sequence: reproduce, check the instrumentation, swap in a known-good unit or recorded input, log at the boundary, then bisect. Say which result would move the suspicion from one side to the other.

Overclaiming embedded or low-level experience on the CV

State the exact layer, target and language you worked with and what you owned. Candidates report deep dives into anything listed, including pros and cons, so cut or qualify items you cannot defend.

Telling the resource-constrained optimization story without a baseline or numbers

Bring the constraint, the measurement method, the before and after figures and the trade-off you accepted. If you lack numbers from a past job, pick a smaller project where you can reproduce them.

Giving a generic answer to the company, career-goal and delivery-speed questions

Tie the company answer to the reported products (diagnostic tools, fleet management, connectivity) and a project of yours. Give a concrete rule for speed versus maintainability, such as shipping the thin version with tests and logging the debt, and be able to say it in both English and Spanish.

Questions & practice

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

  1. 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.
  2. 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.
  3. 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.
  4. 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?

Track a rolling failure rate per destination for circuit decisions

Easy · sliding window · ring buffer · circuit breaker

The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.

Approach

  1. Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
  2. Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
  3. State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
  4. Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.

Follow-up

  • The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
  • A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?

Collapse a redelivered event batch into per-aggregate high-water marks

Easy · hashing · at-least-once · aggregation

You drain a batch of up to 5,000,000 events, each (aggregate_id BIGINT, aggregate_version INT, event_type, payload). The log guarantees order within one aggregate only; the batch merges 64 partitions, and a relay failover has redelivered a range, so an older version for an aggregate can appear after a newer one. Given a map of last_applied_version per aggregate, produce the events worth applying, at most one per (aggregate_id, version), plus the count discarded. Target O(n) time. State the memory for 2,000,000 distinct aggregates and what you do when it does not fit.

Approach

  1. One pass, one hash map from aggregate_id to the highest version kept, and a discard counter. An event whose version is at or below last_applied_version for its aggregate is dropped without further work, which is the whole reason the event carries its version rather than a delta. O(n) expected time, O(d) space in distinct aggregates.
  2. Keep the maximum, never the last occurrence. The redelivered range means the final appearance of an aggregate in the batch can be an older version than one seen earlier in the same batch, so last-wins applies stale state over newer state and the projection regresses with no error anywhere.
  3. Cost the memory instead of calling it large: an 8-byte key plus a 4-byte version is 12 bytes of payload, and an open-addressed table held at a 0.7 load factor costs roughly 17 bytes per entry before per-slot metadata, so 2,000,000 aggregates is tens of megabytes in a native layout and several times that in a runtime that boxes both key and value.
  4. If the distinct set exceeds memory, partition on hash(aggregate_id) mod P and reduce each partition independently. Every event for one aggregate hashes to the same partition, so the per-partition result is exact and the merge is concatenation rather than a second reduction.

Follow-up

  • The payload is a patch rather than a snapshot, so applying only the highest version loses the intermediate changes. What changes in your reduction?
  • How do you detect that version 7 arrived while version 6 was never delivered, and what should the consumer do about the gap?

Explain why the owner filter ignores the listing index

Medium · composite index · query plans · sort elimination

The only index on resource is (tenant_id, status, updated_at DESC, resource_id DESC). A new endpoint returns one user's resources across all statuses, newest created first: WHERE tenant_id = $1 AND owner_user_id = $2 ORDER BY created_at DESC LIMIT 20. On a tenant with 2M rows it takes 900 ms and EXPLAIN shows a sort above a large scan. Explain precisely why the existing index cannot serve it, give the index that can, and state which of these the new index still will not help: owner_user_id alone across tenants; the same query ordered by updated_at. PostgreSQL 16.

Approach

  1. Separate the two jobs an index does. For filtering, a composite btree is seekable only on a left prefix, so with no predicate on status the scan can at best range over tenant_id and test owner_user_id per row; PostgreSQL 16 has no btree skip scan to jump the unconstrained column.
  2. For ordering, the index is sorted by (status, updated_at) within a tenant and not by created_at, so the LIMIT cannot stop early: every matching row is read and then sorted. That is the 'Sort Method: top-N heapsort' line, and it is why the plan reads 2M rows to answer with 20.
  3. Derive the replacement from the access path — equality, equality, then the ordering column: CREATE INDEX CONCURRENTLY ON resource (tenant_id, owner_user_id, created_at DESC). The scan seeks to the (tenant, owner) range and walks 20 entries in order, so the Sort node disappears along with the row-read.
  4. Treat INCLUDE (title, status) as conditional, not free. An index-only scan still visits the heap for any row whose page is not marked all-visible, so on a table taking 1.2k writes/second the win depends on autovacuum keeping the visibility map current, and the wider index costs more on every insert.

Follow-up

  • 90% of rows are status='active'. Would a partial index WHERE status = 'active' change your answer, and for which of the three queries?
  • A dashboard runs this for 40 owners in one page load. What changes about the design?

Hold a per-tenant active cap against concurrent creates

Hard · write skew · isolation levels · constraints

A tenant on the standard plan may hold at most 50 resources with status='active'. The create handler runs SELECT count(*) FROM resource WHERE tenant_id = $1 AND status = 'active', compares to 50, then inserts. Two creates arrive 3 ms apart on different instances and the tenant lands at 51. Name the anomaly, say whether PostgreSQL 16 READ COMMITTED or REPEATABLE READ prevents it and why, then give an implementation that holds the cap at READ COMMITTED with the exact statements. Finally, say what changes when the cap is 'at most one running export per tenant' on job_run.

Approach

  1. Name it: write skew. The two transactions read an overlapping set and write disjoint rows, so there is no row-level conflict for the engine to detect and each commit is individually legal.
  2. Rule out the levels precisely. READ COMMITTED takes a fresh snapshot per statement and takes no lock on the counted rows, so both see 49. PostgreSQL's REPEATABLE READ is snapshot isolation: it removes non-repeatable reads and phantoms within the snapshot but still admits write skew, because the anomaly is not a re-read of a changed row, it is a read of a set that a concurrent transaction invalidates. Only SERIALIZABLE closes it, by tracking the read dependency and aborting one transaction with SQLSTATE 40001 — a guarantee that exists only if the application re-runs the whole transaction from the read.
  3. Convert the set predicate into a single-row conflict: keep tenant.active_resource_count and run UPDATE tenant SET active_resource_count = active_resource_count + 1 WHERE tenant_id = $1 AND active_resource_count < 50 in the same transaction as the INSERT. Zero affected rows is the cap, returned as 409. The row lock serialises the decision at any isolation level, and contention is bounded to one tenant's row — which is also the fair-scheduling unit, unlike a global counter that would convoy every tenant behind one row.
  4. State the cost you just took on: a counter is a second source of truth that can drift, so every path that changes status must adjust it inside the same transaction, and a periodic reconciliation has to exist, with resource_revision as the authority for what the count should have been.

Follow-up

  • A resource moves from archived back to active. Which statements change, and what breaks if the counter update and the status change land in different transactions?
  • The cap becomes plan-dependent and a plan can change mid-month. Where does the number 50 live, and who reads it?

Can you explain the basic principles of electronic circuits and how they interface with software?

Medium · Technical Fundamentals and Electronics

Approach

  1. Start with the basics that matter for software: Ohm's law (V = I x R), power (P = V x I), and the voltage divider. Say what a pull-up or pull-down resistor is for: it stops a GPIO input from floating to random values when nothing drives it.
  2. Walk the boundary from the analogue side to the digital side. Logic levels (3.3 V vs 5 V parts need level shifting), GPIO for on/off signals, PWM for driving loads, and the ADC for sensors. Do one calculation: a 12-bit ADC with a 3.3 V reference resolves about 0.8 mV per step (3.3 / 4096).
  3. Compare the common buses by their trade-offs. UART is asynchronous and both ends must agree on the baud rate. I2C uses two open-drain wires that need pull-ups, with addressed devices. SPI is full duplex with a chip-select line per device and is faster. CAN is a differential, multi-master bus where the lower message ID wins arbitration.
  4. Explain how software sees the hardware: memory-mapped registers, polling versus interrupts, and why a register or a flag shared with an ISR is declared volatile in C/C++ (the compiler must not cache it).
  5. Close with the edge cases software has to absorb: switch bounce (debounce in software or with an RC filter), electrical noise on sensor readings (averaging, hysteresis), and reads that time out because a device on the bus never answers.

Follow-up

  • Why does an I2C bus need pull-up resistors, and what happens if they are too weak?
  • A sensor value jitters even though the physical quantity is stable. What would you change in hardware and what in software?
  • When would you poll a peripheral instead of using an interrupt?

Tell us about your professional background and the most complex project you have led.

Medium · Professional Experience and Growth

Approach

  1. Keep the background short and in order: the domains you worked in, the languages you used (C++, Python and C# are the ones candidates report for this role), and the thread that leads to this application. Then spend most of the answer on one project.
  2. For the project, describe the architecture before the story: the modules, how they talk to each other (API, message queue, shared memory, serial bus), and where hardware or external systems sit. A simple diagram you can describe in words works well.
  3. Separate what you decided from what the team did. Name two or three decisions you made, the option you rejected for each, and the reason: performance, maintainability, cost, or a constraint from hardware.
  4. Give evidence: a number before and after (latency, memory, defect rate, release frequency) and how you measured it. Include one thing that went wrong and what you changed because of it.
  5. Candidates report being asked about the pros and cons of any technology on their CV, so for each tool you name, have one strength, one weakness and one alternative ready.

Follow-up

  • Why did you choose that language or framework over the obvious alternative?
  • Which part of that system would fail first if the load or the number of devices grew tenfold?
  • How did you test it, and what did your tests miss?

Why are you interested in joining Cojali S. L. specifically, and what do you know about our current products?

Medium · Professional Experience and Growth

Approach

  1. Show you know what the company builds as candidates describe it: diagnostic tools for vehicles, fleet management platforms and connectivity solutions, with software sitting next to automotive hardware. Pick one of these areas rather than listing all three.
  2. Turn that area into a concrete engineering problem and show you have thought about it. Fleet management implies ingesting data from many vehicles over unreliable links (buffering, retries, idempotent uploads). Diagnostics implies software talking to vehicle electronics through standard protocols, where a background in OBD-II or CAN-based protocols helps.
  3. Link the problem to something you have already done: a backend that handled intermittent clients, embedded work, a hardware integration, or a C++/Python/C# codebase. One specific link is stronger than general enthusiasm.
  4. Candidates report that interviews can be held in English or Spanish depending on the team, so rehearse this answer in both languages. Candidates also report that showing commitment to working in the company's area helps, so say so if it is true.
  5. Avoid generic praise of the company and anything about pay. Finish with a question that shows you researched the products, for example how the diagnostic software is updated in the field.

Follow-up

  • Which of the product areas would you most want to work on, and what would you need to learn first?
  • What technical problem do you think is hardest in fleet connectivity?
  • Have you used any vehicle diagnostic tool yourself, and what did you notice about it?

How do you balance the need for fast delivery with the necessity of clean, maintainable code?

Medium · Professional Experience and Growth

Approach

  1. Say you decide case by case by reversibility. Interfaces, data formats and protocols that deployed devices or other teams depend on are expensive to change, so they get the extra design time. Internal implementation details behind a clean interface can ship simpler and be improved later.
  2. Name the guardrails that keep speed cheap: tests at module boundaries, code review, CI with linting and static analysis, and small merges. These cost little on each change and stop shortcuts from spreading.
  3. Explain how you take on debt deliberately: write down the shortcut in a ticket with an owner and a trigger for paying it back (the next feature in that area, or a defect count), instead of leaving a comment nobody reads.
  4. Point out that the bar depends on the cost of a fix. Code that runs on hardware in the field, where an update is slow or risky, deserves a higher bar than a web dashboard that can be redeployed the same day.
  5. Back it with one real example: the deadline, the shortcut you took or refused, and what happened afterwards, with a number if you have one.

Follow-up

  • Tell me about a shortcut you took that cost more later. What would you do differently?
  • How would you convince a manager to give you time for a refactor?
  • What is your minimum quality bar for an urgent hotfix?

What are your long-term career goals, and how do they align with a role here?

Medium · Professional Experience and Growth

Approach

  1. Give a specific, honest direction rather than a job title: for example deeper embedded and hardware-software integration, owning the architecture of a backend service, or leading a small team. Say what you want to be able to do, not only what you want to be called.
  2. Tie the goal to work this role involves as candidates describe it: the full lifecycle from design to maintenance, working with hardware engineers, and products in diagnostics, fleet management and connectivity.
  3. Show that you are already moving towards it: a course, a side project with a microcontroller, a protocol you studied, or responsibility you took on in your current job.
  4. Avoid goals that point away from the role (a planned move to another field or a startup soon) and vague answers like 'keep learning'. Do not raise pay here.
  5. If the interview runs in Spanish, rehearse this answer in Spanish as well; candidates report that some teams switch between English and Spanish.

Follow-up

  • What have you done in the last year to move towards that goal?
  • What would you need from a team or a manager to get there?
  • If this role turned out to be mostly backend work, how would that fit your plans?

How do you approach debugging a system where the issue could be either software or hardware-related?

Medium · Technical Fundamentals and Electronics

Approach

  1. Characterise the fault before blaming either side: is it deterministic or intermittent, does it hit one unit or every unit, and did it start with a firmware or software version, a hardware revision, or a change in conditions (temperature, supply voltage, vibration)? One unit failing points towards hardware; every unit failing after a release points towards software.
  2. Bisect across the boundary by swapping one variable at a time: known-good firmware on the suspect board, suspect firmware on a known-good board. Each swap rules out half the candidates whichever way it turns out.
  3. Measure at the boundary instead of trusting logs. Put a logic analyser or oscilloscope on the bus to check that the bytes on the wire match what the code believes it sent, and use a multimeter or scope on the supply rails to catch brownouts. Read the reset-cause register to tell a watchdog reset from a power dip.
  4. Watch for the software faults that look like hardware: race conditions with ISRs, stack overflow, uninitialised memory, wrong timing after a clock change. If adding print statements makes the bug vanish, timing is involved, so switch to a RAM ring buffer or toggle a spare GPIO and scope it.
  5. Call it fixed only when you can make the fault appear and disappear on demand. Then add a regression test or a hardware-in-the-loop check so the same fault cannot come back silently.

Follow-up

  • The bug disappears as soon as you add logging. What does that tell you, and how do you instrument it instead?
  • A reading fails on a small fraction of units in the field and never on your bench. How do you collect evidence from deployed devices?
  • How do you tell a noisy signal from a software parsing bug on a serial link?

Suggested practice checklist

The plan follows the two reported rounds: day one maps your CV, days two to four cover the hardware-software, debugging and low-level material, days five to six cover career stories and a backend refresher, and day seven is a bilingual mock.

Day 1 — Map the loop and audit your CV

  • Write the two reported rounds, Professional Background Review then Technical Assessments, and mark which one you are less ready for
  • List every project and technology on your CV; for each technology write one strength, one weakness and one case where you would avoid it
  • Mark each project that touched hardware, devices or low-level code, since the reported questions lean that way

Deliverable: A one-page loop map plus a CV audit table of technologies with pros, cons and the projects that used them.

Day 2 — Electronics-to-software fundamentals

  • Trace a single sensor reading from voltage to application variable: conversion, sampling, bus, driver, parsing, units
  • Write short definitions you can say aloud for pull-up resistors, debouncing, polling versus interrupts and sampling rate
  • Answer the circuits-and-software question aloud and record yourself

Deliverable: A one-page signal-path diagram, a glossary of the terms above and one recorded spoken answer.

Day 3 — Debugging across the software-hardware boundary

  • Write a debugging checklist: reproduce, check instrumentation, swap known-good parts, log at the interface, replay recorded input, bisect
  • Outline a software component for a new hardware sensor: interface, adapter, timeout and error states, simulator, calibration, tests
  • Answer the software-or-hardware debugging question aloud, using a real bug of yours as the example

Deliverable: A debugging checklist, a sensor-component design outline and one spoken answer with a real example.

Day 4 — Low-level and performance stories

  • Write the embedded or low-level experience story: layer, target, what you owned, how you tested without hardware
  • Write the resource-constrained optimization story with constraint, baseline, change, result and trade-off, using real figures
  • Practise both aloud and cut anything that is not a decision you made

Deliverable: Two written stories with numbers, each rehearsed aloud at least once.

Day 5 — Background, complex project and delivery trade-offs

  • Write the two-minute background narrative and a detailed walk-through of the most complex project you have led
  • Write your rule for fast delivery versus clean, maintainable code, with one example where you shipped thin and one where you refused to
  • Rehearse both in English, then in Spanish, noting vocabulary you hesitate on

Deliverable: A background narrative, a project walk-through and a written delivery-versus-maintainability rule, with a bilingual vocabulary list.

Day 6 — Backend and code-quality refresher

  • Pick your strongest of C++, Python or C#, and refresh testing, version-control workflow and documentation habits you can describe
  • Solve the rolling failure-rate and redelivered-event practice problems in that language, explaining complexity aloud
  • Write a short architecture sketch of a backend service you built: modules, how they communicate, and what breaks first under more load

Deliverable: Two solved practice problems with stated complexity and a one-page architecture sketch of your own service.

Day 7 — Company answer, goals and full mock

  • Write your answer on why Cojali S. L. and what you know about its products, naming one product area and a project of yours that connects to it
  • Write your long-term goals answer and decide your salary expectation for the HR screening
  • Run a full mock of both rounds, switching language halfway, then practise the integration-deprecation behavioral prompt as a communication drill

Deliverable: A company answer, a goals answer, a salary line, a recorded two-language mock and two questions to ask the team about its current challenges.

Embedded, performance and career stories

The reported behavioral material for this role is split between hardware-adjacent stories (embedded or low-level experience, and optimizing under resource limits) and career stories (background, most complex project, delivery versus maintainability, goals). Candidates also report being asked about how they handle feedback and cross-functional work. Prepare two or three real projects and reuse them across prompts, each with the decision you made, the evidence you used and what it cost.

  1. Describe your professional background and the most complex project you have led.
  2. How do you balance the need for fast delivery with the necessity of clean, maintainable code?
  3. What are your long-term career goals, and how do they align with a role here?
  4. Why Cojali S. L. specifically, and what do you know about its current products?

What is your experience with embedded systems or low-level programming?

Medium · Technical Fundamentals and Electronics

Approach

  1. Open with the layer you worked at, in one sentence: firmware on a microcontroller, a device driver, a protocol parser in C or C++ reading from a serial bus, or userspace code talking to hardware. Name the language, the target and what you personally owned.
  2. Walk one concrete example: what the hardware exposed (datasheet, register map, bus), how you read or wrote it (polling or interrupt, buffering), and how you handled timing, byte order and partial frames. Finish with how you tested without the board, using a simulator or recorded traces.
  3. Show the fundamentals you actually used: stack versus heap, fixed-size buffers instead of dynamic allocation on small targets, volatile for memory-mapped registers, short interrupt handlers that defer work to the main loop, bit masks for flags. Claim only what you have done.
  4. If your experience is thin, say so in the first sentence and bridge honestly: C++ with manual memory management, profiling, binary protocol parsing, Linux system calls, or a hobby board, plus what you would learn first. The failure mode is a vague 'I have done embedded' that falls apart at the first follow-up on a technology on your CV.

Follow-up

  • What happens if an interrupt fires while the main loop is updating the same variable, and how would you protect it?
  • How did you test the code when the hardware was not available?
  • Which part of that work would you do differently in Python than in C++, and why?

Describe a time you had to optimize code for performance in a resource-constrained environment.

Medium · Technical Fundamentals and Electronics

Approach

  1. Name the constraint precisely: RAM or flash size, CPU budget, power, bandwidth or a latency deadline, and the target you had to hit. Use the real numbers from your project; do not round them into something impressive.
  2. Describe the baseline before the change: how you measured (a profiler, timestamps in logs, a timer, a size report from the build) and what the hot spot was. The mistake that sinks this story is optimizing by hunch with no before figure.
  3. Describe one or two specific changes and why each fit the constraint: removing allocations from the hot path, reusing preallocated buffers, avoiding copies, replacing repeated computation with a lookup table, integer or fixed-point math on hardware without a floating-point unit, batching I/O, or a lower-complexity algorithm.
  4. Close with before-and-after numbers and the trade-off you accepted (readability, memory for speed, generality), how you proved behaviour was unchanged (tests against the old output), and how you stopped it regressing (a benchmark, a comment explaining the odd code). This also supplies material for the delivery-versus-maintainability question.

Follow-up

  • How did you know that was the bottleneck and not something else?
  • What did the optimization cost in readability, and how did you contain it?
  • What would you change if the target had half the memory?

Tell callers you do not own that their integration breaks

Medium · deprecation · compatibility · stakeholders

A field in a write endpoint's response must change shape. You own the endpoint; you do not own the four internal callers or the outbound webhook consumers who read it. Describe a deprecation you were responsible for: what you shipped first, how you established who was actually reading the field, the window you gave and what set its length, what you did about the consumer who never moved, and how you decided removal was safe. Name the signal you used, not the announcement you sent.

Approach

  1. Establish the reader set empirically rather than from a wiki of owners: per-field usage counters keyed by principal, or access logs attributed to a consumer. State the blind spot of whichever you pick, since a consumer that reads the field only on a monthly job will not appear in a week of logs.
  2. Ship additive first. Populate the new field alongside the old one so no reader is forced to move, which is also what keeps a rolling deploy safe, because old and new instances answer the same requests at the same time and a rollback must still find the old shape present.
  3. Set the window from the slowest legitimate consumer's release cadence, not from your calendar, and decide separately what to do for a consumer with no release process at all, such as an external webhook endpoint you can only email.
  4. Convert silence into evidence before you rely on it: a short, low-traffic removal window that makes a still-dependent consumer fail visibly and loudly while you are watching, rather than at three in the morning after you have moved on.

Follow-up

  • How would you detect a consumer that reads the field only during a monthly export?
  • One caller refuses to move and has a commercial relationship behind it. What changes in your plan and what does not?