cswork / libraryOpen practice workspace

Interview guides · Arity

Arity Software Engineer Interview Guide

Arity Software Engineer interview guide: four reported rounds, paired programming, cloud and system design questions, and a seven-day preparation plan.

The 60-second brief

Arity is described by candidates as a mobility data analytics company that operates as a subsidiary of Allstate. It collects and analyzes driving data, and the products named in the role description include consumer-facing applications, predictive risk models and cloud platforms. For a Software Engineer, candidates describe work such as building microservices that ingest real-time telematics streams, running those services on a public cloud, and automating infrastructure and deployments. The role is described as sitting alongside product managers and data scientists, so part of the job is turning a model or a business requirement into a service that runs reliably in production.

This guide is for candidates interviewing for a Software Engineer position at Arity, especially backend, cloud platform or distributed-systems profiles. It covers the four reported rounds, the technical areas candidates report (cloud architecture, paired programming and refactoring, system design, debugging in production), the behavioral questions, and a seven-day schedule that sends you to the right practice material for each.

Candidates report four rounds over roughly 3-5 weeks: a recruiter screen, hands-on technical evaluations built around paired programming, conversations with engineering managers and senior engineers, and final rounds with directors.

Focus areas

  • Cloud Platform Engineering
  • Paired Programming
  • System Design

Overview

Candidates describe the Software Engineer role as cloud and backend work around telematics: services that take in streams of connected-car events, pipelines that process them, and the infrastructure automation underneath. The requirements they list are one general-purpose language (Java, Python or Go are named), experience on AWS, GCP or Azure, and working knowledge of Docker and Kubernetes. Event-driven tools such as Kafka or RabbitMQ, Terraform, big data frameworks and prior telematics work show up as nice-to-haves. That list tells you where to spend time: be able to discuss a real system built on those pieces, not just name them.

The evaluation areas candidates report fall into three groups. Cloud architecture and infrastructure covers microservices patterns, infrastructure as code and security (encryption in transit and at rest, access control). Software development and coding covers data structures, test-driven development and refactoring, mostly in live or paired sessions. System design and scalability covers storage choices between relational, NoSQL and time-series stores, caching, and asynchronous processing with queues. Practise each of these out loud: the paired format means your reasoning is part of the work product, and a correct but silent solution gives you less to show.

The reported question set is a mix. On the design side it includes securing a microservices architecture, state and consistency in distributed systems, and database query performance under high throughput. On the coding side it includes filtering a large telemetry stream, refactoring legacy code with a partner, debugging a production memory leak and describing a test-driven workflow. One question even asks about voltage and current over time in circuits, which is unusual for a software role, so give it a short refresher rather than a long study block. The behavioral questions cover your background, a technical disagreement, prioritising under ambiguity and owning a project from conception to deployment. The plan below gives each cluster its own day.

The Arity interview process

Candidates describe four stages, and say exact scheduling and the combination of rounds can shift with the team or the seniority level you are targeting. The descriptions below separate what is reported from how to prepare.

Recruiter Screen

Candidates describe this first stage as a conversation with a recruiter about your background and why you want the role. Treat it as the place to connect your experience to the stack the role lists: one language from Java, Python or Go, a cloud platform, containers, and event-driven tooling if you have used it. The background and motivation question reported for this loop (why you want to join Arity) is the one to rehearse for this stage. It is also the moment to ask the recruiter what the technical stage looks like, since candidates describe it as interactive and hands-on.

What to demonstrate

  • How clearly you summarise your background and relate it to a backend or cloud platform role
  • Whether your reason for choosing Arity and the mobility and telematics space is specific rather than generic
  • Whether your language and cloud experience line up with the requirements candidates describe

How to prepare

  • Write a short career narrative in three parts (where you are now, the projects that led here, what you want next) and name two projects involving services, pipelines or cloud infrastructure.
  • Write a why-Arity answer that survives the swap test: if you can replace the company name with another and the answer still works, add a concrete link to driving data, telematics or safety.
  • Prepare questions for the recruiter about the format of the technical stage, the tools used for pairing and which language you can use.

Technical Evaluations

Candidates report hands-on technical evaluations that emphasise paired programming and practical problem solving, with a collaborative online coding environment. The areas reported for coding are data structures and algorithms, test-driven development, refactoring existing code and writing tests for asynchronous workflows. This is the stage where questions like filtering a large telemetry stream, refactoring messy legacy code with a partner, and describing a test-first workflow are practised. Work as a pair: state assumptions, write a small test, make it pass, then change the code in small steps while talking through each one.

What to demonstrate

  • Working code produced in a shared session, which is what a paired programming format exercises
  • How you break down a practical problem and state your assumptions and trade-offs aloud
  • Your testing and refactoring habits on code you did not write

How to prepare

  • Choose one language and practise in a plain editor with its test runner: write a failing test first, then the smallest code that passes.
  • Practise a stream-processing function that filters, deduplicates and tolerates out-of-order events without holding the whole input in memory.
  • Take a messy function, add characterization tests that pin its current behaviour, then refactor in small steps (extract, rename, remove duplication) and rerun after each step.
  • Practise explaining a testing strategy for asynchronous code: fake clocks, awaiting a condition instead of sleeping, and isolating the queue or network boundary.

Meet Engineering Managers

Candidates report interviews with engineering managers and senior engineers that look at technical depth and teamwork. The reported evaluation areas for conversations like this include cloud architecture (microservices, infrastructure as code, security) and system design (storage choices, caching, asynchronous processing), so the questions on securing microservices, distributed state and consistency, query optimisation, containers and production debugging are good practice material for this stage. Pick one or two systems you built, and be ready to go from the high-level design down to the data model, the failure modes and what you would change.

What to demonstrate

  • Depth of knowledge in the cloud and distributed-systems topics the role lists, shown through systems you have actually run
  • Teamwork, including how you handle a disagreement about a technical choice
  • Whether design decisions are justified with trade-offs rather than tool names

How to prepare

  • Prepare a design walk-through of a telemetry ingestion pipeline: ingest endpoint, queue, stream workers, storage choice, alerting path, and what happens when a downstream store is unavailable.
  • Write a one-page threat model for a microservices deployment: trust boundaries, service-to-service authentication, secrets handling, least-privilege access, encryption in transit and at rest.
  • Rehearse two debugging stories, one memory leak or resource exhaustion and one performance regression, with the evidence you gathered at each step.
  • Have your Docker and Kubernetes experience ready as specifics: what you deployed, how you rolled out and rolled back, and one incident you diagnosed.

Final Leadership Rounds

Candidates describe the final stage as interviews with directors that assess fit with the team and organisational goals. Expect the conversation to be about how you work and decide, so the ownership, prioritisation and background questions reported for this loop are the natural material, along with your reasons for wanting mobility and telematics work. Have a project you took from idea to production, an example of choosing what to do first when requirements were unclear, and a few questions of your own about the team and its technology direction.

What to demonstrate

  • Fit with the team and its goals, as the stage is described
  • Ownership of delivery, from conception through deployment and operation
  • How you prioritise when deadlines compete and requirements are ambiguous

How to prepare

  • Write the ownership project as a sequence of decisions (scope, design, test, rollout, monitoring) and mark the ones you made yourself.
  • Prepare a prioritisation answer using a real situation: what you cut, who you told, and how you confirmed the call was right afterwards.
  • List three questions about team structure, stack evolution and how production issues are handled, and tailor them to what you learned in earlier rounds.

Where candidates lose points

Answering the secure microservices question with a list of tools (service mesh, API gateway, secrets manager) and no threat model.

Name the trust boundaries first: where traffic enters, how services authenticate to each other, where secrets live, what each service's role may access, and what is encrypted in transit and at rest. Then say what fails when one service is compromised or down.

Starting the telemetry-stream function by reading everything into a list, with no word on duplicates, out-of-order events or memory.

Ask about event shape, ordering and volume, then process incrementally with a generator or iterator, keep only bounded state (a dedup window, a watermark), and write a test for the empty stream, a duplicate and a late event before extending it.

Rewriting the messy legacy function wholesale in the paired session without tests, so nobody can tell whether behaviour changed.

Write characterization tests that pin current output first, then refactor in small steps (extract function, rename, remove duplication, simplify conditionals), running the tests after each step and saying aloud what each step preserves.

Answering the production memory leak by suggesting more memory or a restart schedule.

Confirm that memory grows without bound under steady load, take comparable heap snapshots or profiles at two points, find what retains the growing objects, fix it, and prove it with a soak test. Name the tool for your language (heap dump analysis, tracemalloc, pprof) and say how you would do it safely in production.

Telling behavioral stories in the team's voice throughout, or giving a why-Arity answer that fits any employer.

Use I for your own decisions and name the others involved. For motivation, tie the answer to mobility data, telematics or safety and to something you built, and finish each story with a result and what you would change.

Questions & practice

Write a function to process and filter a large stream of telemetry data efficiently.

Medium · Paired Programming and Problem Solving

Approach

  1. Clarify the record shape (device id, timestamp, sequence number, readings), the filter rules, whether order matters, and whether the stream is unbounded. That decides whether the function can hold state or must be a pure per-record filter.
  2. Process lazily: write a generator or iterator that reads one record, validates it, and yields it or drops it. That is O(n) time in a single pass and O(1) memory per record, and it composes cleanly (parse, then validate, then filter, then batch) without ever loading the whole stream.
  3. Make the filters concrete: drop malformed or unparseable rows, null or out-of-range values (impossible speeds, GPS coordinates outside valid bounds), and duplicates keyed on (device_id, sequence). Keep dedupe state bounded with a TTL map or a per-device last-seen sequence so memory grows with active devices, not with total events.
  4. For rolling rules such as a speed threshold over the last N readings, keep a per-device deque with a running sum so each update is O(1). Handle late or out-of-order events with a watermark or an allowed-lateness window rather than assuming timestamps arrive sorted.
  5. Cover the edge cases with tests: an empty stream, an all-invalid batch, clock skew, a device that goes silent, and a record that fails parsing. Log or count dropped records instead of failing silently.

Follow-up

  • The dedupe set no longer fits in memory; what do you trade off by switching to a Bloom filter (no false negatives, some false positives)?
  • How would you parallelise this across workers while keeping each device's events in order?
  • How does your function behave when the downstream consumer is slower than the producer?

Collaborate with the interviewer to refactor a messy piece of legacy code during a paired programming session.

Medium · Paired Programming and Problem Solving

Approach

  1. Agree with your pair on the goal before touching code (readability, a specific bug, a performance target, or making room for a new feature), and say out loud that behaviour stays the same while the structure changes.
  2. Write characterization tests first that pin the current behaviour, quirks included, using the real inputs the function sees. Without them you cannot tell a refactor from a behaviour change.
  3. Refactor in small steps with the tests passing after each one: rename unclear variables, extract functions out of long blocks, flatten nested conditionals into guard clauses, and remove duplicated branches. Use the IDE's automated refactorings where possible, because they are less error-prone than hand edits.
  4. Separate side effects from logic. Pull I/O, clocks, globals and database calls behind parameters or small interfaces so the core logic becomes a pure function you can test directly.
  5. Name the risks as you go (hidden callers, mutation of shared state, exceptions used for control flow) and keep any behaviour change, such as a bug fix you find, in a separate, clearly labelled step.

Follow-up

  • You find a bug while refactoring that callers may depend on; do you fix it now, and how?
  • How do you decide when to stop refactoring and ship?
  • The function has no tests and is hard to call in isolation; what is your first move?

Walk through your test-driven development process when building a new feature from scratch.

Medium · Paired Programming and Problem Solving

Approach

  1. Turn the feature into acceptance criteria and a short list of test cases (the happy path, boundaries, invalid input, failure of each dependency) before writing any production code.
  2. Run the red-green-refactor loop: write the smallest failing test, write just enough code to make it pass, then clean up the code and tests while everything stays green. Each cycle should be small enough that a failure points to one change.
  3. Keep units fast and isolated: inject dependencies such as clocks, HTTP clients and repositories so you can pass in fakes, and prefer fakes over deep mock chains that tie tests to implementation details.
  4. Add integration tests at the real boundaries (the database, the message queue, external APIs), for example with containerised dependencies, plus a few end-to-end checks. The result is a pyramid: many unit tests, fewer integration tests, very few end-to-end tests.
  5. For asynchronous workflows, control time and ordering explicitly (an injected clock, awaiting completion, polling with a timeout) instead of sleep calls, which make tests flaky.

Follow-up

  • When would you skip writing the test first, and what do you do instead?
  • Your test suite has become slow and flaky; how do you fix it?
  • How do you test-drive code that consumes events from a queue and retries on failure?

How do you prioritize tasks when faced with competing deadlines and ambiguous requirements?

Medium · Behavioral and Background Questions

Approach

  1. Treat this as a behavioural question and answer with one real example in STAR form: the competing deadlines, who owned each one, and what was unclear in the requirements.
  2. Show the method: I listed the work with each item's impact, deadline, dependencies and how reversible a delay would be, then ranked it. Low-impact work that blocked other people moved up; work whose deadline I could negotiate moved down.
  3. Show how you handled the ambiguity: the specific questions you took to the product owner or stakeholder, the assumption you wrote down and shared when no answer came, and how you shipped a small first slice to test that assumption.
  4. Say what you dropped or deferred and how you told the affected people early, then give the outcome with something checkable (what shipped, what slipped, and whether the trade-off held up).
  5. Avoid the answer that sinks this question: 'I worked longer hours to do everything', or a story with no trade-off and no stakeholder conversation.

Follow-up

  • Tell me about a time your prioritization turned out to be wrong; what did you change?
  • Two stakeholders each say their task is the top priority; how do you resolve it?
  • How do you decide when requirements are clear enough to start building?

Stop tag and share joins from fanning out a page

Medium · join fan-out · semi-joins · many-to-many

resource_tag is (resource_id, tag_id) with PK (resource_id, tag_id); resource_share is (resource_id, shared_with_user_id, permission). The tagged-and-shared listing inner-joins resource to both, filters tenant_id, tag_id = ANY($2) and shared_with_user_id = $3, orders by updated_at DESC and takes 50. Pages come back with fewer than 50 distinct resources and the total in the header is far too high. Explain the row multiplication, rewrite both the page query and the count query so each is correct, and name the index each one needs. PostgreSQL 16.

Approach

  1. Do the arithmetic against the predicates that are actually there. An inner join emits one row per matching child row, and both joins are filtered: tag_id = ANY($2) admits only the requested tags, shared_with_user_id = $3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
  2. Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
  3. Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
  4. Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.

Follow-up

  • The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
  • A resource can be shared with the same user twice under different permissions. Does your count change, and should it?

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

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

Explain the voltage or current behavior over time for different circuits.

Medium · Technical and Domain Questions

Approach

  1. Start with the two continuity rules: a capacitor's voltage cannot jump instantly but its current can, and an inductor's current cannot jump instantly but its voltage can. At DC steady state a capacitor acts as an open circuit and an inductor as a short.
  2. RC step response: charging gives v_C(t) = V(1 - e^(-t/RC)) and the current decays as (V/R)e^(-t/RC). The time constant is tau = RC; after one tau the voltage reaches about 63% of its final value, and after 5 tau it is within about 1%.
  3. RL step response: inductor current rises as i(t) = (V/R)(1 - e^(-t/tau)) with tau = L/R, while the inductor voltage starts at V and decays exponentially. Opening an inductive circuit suddenly causes a voltage spike (L di/dt), which is why flyback diodes exist.
  4. Series RLC: the natural frequency is w0 = 1/sqrt(LC) and the damping ratio is zeta = (R/2)sqrt(C/L). Above 1 the response is overdamped (slow, no overshoot), at exactly 1 it is critically damped, and below 1 it rings at w0*sqrt(1 - zeta^2) inside a decaying envelope.
  5. Sketch each curve with labelled axes, the initial value, the final value and tau, and check energy: 1/2 CV^2 is stored in the capacitor and 1/2 LI^2 in the inductor.

Follow-up

  • What happens to the current the instant you close the switch on an uncharged capacitor, and why?
  • How would you choose R in an RLC circuit so it settles quickly without overshoot?
  • How does an RC low-pass filter's cutoff frequency relate to its time constant?

Walk through how you would design and secure a scalable microservices architecture in the cloud.

Medium · Technical and Domain Questions

Approach

  1. Pin down the scope first: the services, the request rate, the read/write mix and the data that needs protecting. Then split along business boundaries so each service owns its own datastore and no other service writes to its tables.
  2. Edge and identity: put an API gateway or load balancer in front to handle TLS termination, rate limiting and token validation (OIDC/JWT). Inside the cluster, use mTLS between services (through a service mesh or by hand) and least-privilege IAM roles for each service, and keep secrets in a managed secrets store rather than in images or env files.
  3. Network and data security: run workloads in private subnets behind security groups or network policies, encrypt data at rest with managed keys and in transit with TLS, and send audit logs somewhere application roles cannot modify.
  4. Scaling and resilience: keep services stateless so Kubernetes can scale them horizontally (for example with an HPA on CPU or queue depth). Give every call a timeout, use retries with exponential backoff and jitter only on idempotent operations, and add circuit breakers so one slow dependency cannot exhaust every thread pool.
  5. Decouple high-volume ingestion through a queue or log such as Kafka so producers survive consumer slowdowns, and add distributed tracing, metrics and structured logs so you can follow a request across hops.

Follow-up

  • How would you revoke a compromised service's access without redeploying everything?
  • Two services need data from the same business transaction; how do you keep them consistent without a distributed transaction?
  • How do you roll out a breaking API change across services that deploy independently?

What strategies do you use for optimizing database query performance in high-throughput applications?

Medium · Technical and Domain Questions

Approach

  1. Measure before changing anything. Use pg_stat_statements or the slow-query log to find the queries with the highest total time (calls times mean latency), then run EXPLAIN (ANALYZE, BUFFERS) on them to see sequential scans, bad row estimates and sorts that spill to disk.
  2. Index for the access pattern: in a composite index, put equality columns first and the range column last (for example (device_id, recorded_at)); use covering indexes for index-only scans; and avoid wrapping indexed columns in functions or implicit casts. Every extra index slows writes, which matters on a write-heavy workload.
  3. Fix query shape: remove N+1 loops by batching or joining, select only the columns you need, replace deep OFFSET pagination with keyset pagination (WHERE recorded_at < :last ORDER BY recorded_at DESC LIMIT n), and batch inserts or use COPY for bulk loads.
  4. Scale the data layer: partition time-series tables by time so queries can skip whole partitions and old data can be dropped cheaply, use connection pooling (for example PgBouncer) so connections are not exhausted, and send reads to replicas only where replica lag is acceptable.
  5. Cache hot, read-mostly results with an explicit invalidation or TTL policy, and confirm each change by re-running the same EXPLAIN and comparing p95/p99 latency, not just the average.

Follow-up

  • The planner ignores your new index; what are the likely reasons?
  • How would you add an index to a large, busy production table without blocking writes?
  • When would you move a workload off the relational database to a time-series or NoSQL store?

How would you approach debugging a memory leak in a production application under heavy load?

Medium · Paired Programming and Problem Solving

Approach

  1. Confirm it is a leak and not load: plot memory against traffic and time since restart. A leak keeps rising after GC and does not drop when load falls. Check whether it started with a deploy, a config change or a traffic shift, and whether the container is being OOMKilled.
  2. Contain the impact first: keep rolling restarts or raise memory limits to buy time, and take one affected instance out of rotation so you can inspect it without hurting users.
  3. Capture evidence from the runtime: in Java, two heap dumps taken some time apart (jcmd <pid> GC.heap_dump) compared in a tool such as Eclipse MAT for dominators and growing retained sizes; in Python, tracemalloc snapshots compared with snapshot.compare_to(old, 'lineno'); in Go, the pprof heap profile. If the process RSS grows while the heap stays flat, suspect native memory, direct buffers or fragmentation.
  4. Check the usual culprits: caches or maps with no eviction, listeners or callbacks never deregistered, ThreadLocals in pooled threads, unclosed connections or streams, and in-memory queues that grow because a consumer is slower than its producer.
  5. Reproduce with a load test in staging, fix the problem (bound the cache, close the resource, add backpressure), then confirm memory reaches a flat steady state under sustained load and add an alert on memory slope.

Follow-up

  • Memory grows only under peak load and levels off afterwards; is that a leak?
  • How would you find the leak if taking a heap dump would pause the process for too long in production?
  • What metric and alert would have caught this before the first OOM kill?

Suggested practice checklist

The plan follows the reported loop: pitch and recruiter material first, then cloud design, distributed state and queries, streaming and paired coding, production debugging and containers, and finally behavioral stories. Each day links to the reported questions it practises.

Day 1 — Map the loop and write your pitch

  • Write the four reported rounds (Recruiter Screen, Technical Evaluations, Meet Engineering Managers, Final Leadership Rounds) on one page and mark the one you are least ready for.
  • Write your background answer and a why-Arity paragraph, then apply the swap test: replace the company name and cut any sentence that still works.
  • List the stack the role mentions (a language from Java, Python or Go, a cloud, Docker and Kubernetes, Kafka or RabbitMQ, Terraform) and mark where you have real experience and where you have gaps.

Deliverable: A one-page loop map, a written background and motivation answer, and a stack gap list.

Day 2 — Design and secure a cloud microservices system

  • Design a telemetry ingestion service on the cloud you know best: ingest API, queue, stream workers, storage, alerting path. Draw it and state read and write paths separately.
  • Write the security layer: service-to-service authentication, secrets handling, least-privilege roles, network boundaries, encryption in transit and at rest.
  • Sketch how Terraform or another infrastructure-as-code tool would define the network, queue and compute so the setup is reproducible.

Deliverable: One architecture diagram, a security checklist tied to its trust boundaries and an infrastructure-as-code outline.

Day 3 — Distributed state and database performance

  • Make a table of the entities in your telemetry design (trip, event, driver score, alert) with owner, consistency level and the mechanism that protects each: versioned update, idempotency key, or outbox.
  • Write an idempotent consumer in your language that survives duplicates and a crash between the database write and the acknowledgment.
  • Prepare a spoken answer on query optimisation under high throughput: indexes, avoiding N+1 patterns, batching, read replicas, caching with invalidation, and partitioning.

Deliverable: A consistency table, a working idempotent consumer, and a before-and-after note on one query plan.

Day 4 — Streaming code under paired conditions

  • Write the telemetry filter function: input is an iterator of events, output is the filtered stream with duplicate removal and bounded memory. Cover out-of-order arrivals with a lateness window.
  • Write tests first for empty input, one event, duplicates, a late event and an event exactly at the window boundary, then make them pass.
  • Redo it while narrating assumptions and complexity aloud, and note where you got stuck.

Deliverable: A passing function with its test file and a written note of its time and space complexity.

Day 5 — Refactoring and test-driven development

  • Take a messy 50 to 80 line function from an old project or a public repo. Write characterization tests, then refactor it in steps, committing after each green run.
  • Build a small new feature test-first, repeating red, green, refactor at least five times, and keep the commits to show the sequence.
  • Write tests for an asynchronous workflow (a consumer that retries): use a fake clock and a fake queue instead of sleeps.

Deliverable: A commit history showing characterization tests followed by refactor steps, plus a test-first feature and an async test suite.

Day 6 — Production debugging and containers

  • Write a memory leak runbook for your language: confirm growth in a metric, capture two snapshots (heap dump, tracemalloc or pprof heap), diff them, find the retaining path, fix it, and verify with a soak test.
  • Reproduce a leak in a small program, find it with the tool, and note how you would take that snapshot safely on a live instance.
  • Write your Docker and Kubernetes account: a multi-stage Dockerfile, a Deployment with probes and resource limits, and a diagnosis sequence for CrashLoopBackOff and OOMKilled.

Deliverable: A leak runbook, a reproduced and fixed leak, and a container checklist with your own incident account.

Day 7 — Behavioral stories and full run-through

  • Write story outlines for the technical disagreement and the project you owned from conception to deployment, covering situation, decision, evidence and result.
  • Prepare a prioritisation answer for competing deadlines and ambiguous requirements, using a real case and what you cut and communicated.
  • Give the circuits question a short refresher: charging and discharging of a resistor-capacitor circuit and the current in a resistor-inductor circuit over time, so you can answer it briefly if it comes up.
  • Record a full spoken run: background, one design question, one coding explanation, one behavioral story. Review it for filler and missing trade-offs.

Deliverable: Two story outlines, a prioritisation answer, a one-page circuits refresher and a recorded mock run with notes.

Background, ownership and disagreement stories

Candidates report background, disagreement, prioritisation and ownership questions across the recruiter, manager and director stages. Prepare real stories where your own decisions are visible, backed by what you measured and what you would change. The two experience questions about distributed consistency and containers below are phrased as behavioral prompts, so answer them with systems you have actually run.

  1. How do you prioritize tasks when faced with competing deadlines and ambiguous requirements?

How do you handle state management and data consistency in distributed systems?

Medium · Technical and Domain Questions

Approach

  1. Start by sorting state into kinds: authoritative records (a trip, an account), derived data (aggregates, caches, search indexes) and ephemeral state (sessions). Pick the consistency level per kind: strong for the source of truth, eventual for derived views. Say this up front instead of arguing about CAP in the abstract.
  2. Give each authoritative entity a single writer path, for example a partition key so that all events for one trip or vehicle land on one partition. Prevent lost updates with optimistic concurrency: a version column and an update that only succeeds when the version still matches.
  3. Plan for at-least-once delivery. Give every event a stable id, make consumers idempotent by recording processed ids or upserting by key, and use a transactional outbox so a database write and the event announcing it commit together instead of a risky dual write.
  4. For work that spans services, avoid distributed transactions. Use a saga with a compensating action per step, and say which steps are not reversible. Order events by event time or a sequence number rather than wall-clock timestamps, because device and server clocks disagree.
  5. Close with the failure cases: duplicates, out-of-order arrival, a partition between nodes, a stale leader (fencing tokens), and how you would detect and repair drift between the source of truth and a derived store. Anchor it in one system you have run.

Follow-up

  • A consumer writes to a database and then calls an external API. How do you make a retry safe when the process dies between the two?
  • During a partition between the primary database and the application servers, which operations do you keep serving and which do you refuse?
  • How would you detect and repair a derived store that has drifted from the source of truth?

Describe your experience with containerization and orchestration tools like Docker and Kubernetes.

Medium · Technical and Domain Questions

Approach

  1. Open with one concrete system: what the service did, which containers and cluster you worked with, and what you owned versus what a platform team owned. State that boundary honestly; it is better than claiming control-plane depth you do not have.
  2. Docker specifics: multi-stage builds to keep images small, a pinned and minimal base image, a non-root user, .dockerignore and layer ordering for cache hits, image scanning in the pipeline, and no secrets baked into layers.
  3. Kubernetes specifics: Deployments with a rolling update strategy (maxSurge and maxUnavailable), readiness probes to gate traffic versus liveness probes to restart, resource requests and limits, a horizontal autoscaler driven by CPU or a custom metric such as queue lag, ConfigMaps and Secrets, and a PodDisruptionBudget.
  4. Tell one incident with a diagnosis order: kubectl describe for events, logs with --previous for a crashed container, then the cause, such as CrashLoopBackOff from a bad config, an OOMKilled container from a memory limit set below real usage, or ImagePullBackOff from registry credentials.
  5. Say how a release moved: pipeline stages, how you verified health, how you rolled back, and whether the manifests lived in Helm or Terraform. The answer that falls flat is a list of tool names with no decision you made.

Follow-up

  • A pod restarts every few minutes under load. Walk through how you find out why.
  • How do you deploy a service that consumes from a queue without dropping or double-processing messages?
  • What is the difference between a request and a limit, and what happens to a JVM service whose memory limit is lower than its heap plus overhead?

Tell me about your background and why you are interested in joining Arity.

Medium · Behavioral and Background Questions

Approach

  1. Shape the answer as present, past, future: what you do now, the two or three projects that explain how you got here, and what you want next. Choose projects that resemble the role: backend services, cloud infrastructure, event or data pipelines, anything dealing with sensor, mobile or high-volume data.
  2. For the why-Arity half, use facts you can verify about the company: a mobility data and telematics business that is part of Allstate. Then link it to something you have built or care about, such as processing event streams, risk scoring, or software that affects safety. Avoid praise that fits any employer.
  3. Tie your background to the requirements candidates list: say which of Java, Python or Go you work in, which cloud you know best, and where you have used Docker and Kubernetes. If you have used Kafka, RabbitMQ or Terraform, say where; if not, say what you would learn first.
  4. End on direction, naming the kind of problem you want to work on next, and hand back a question about the team. The mistake that sinks this answer is a chronological recital of every job followed by a motivation that could be about any company.

Follow-up

  • Which project on your resume would you most want to extend here, and what would you change in it?
  • What draws you to mobility and telematics data compared with other data-heavy domains?
  • What would you need to learn in your first months to be effective on this stack?

Describe a time when you had to resolve a technical disagreement within your team.

Medium · Behavioral and Background Questions

Approach

  1. Choose a real technical disagreement where both options were defensible, for example a queue versus a synchronous call, a schema or storage choice, build versus buy, or when to split a service. A personality conflict with no technical substance does not answer this question.
  2. Show that you understood the other position. Restate what it optimised for (latency, simplicity, operational cost, reversibility) and agree on the criteria before comparing options. This is the step that moves a disagreement from opinion to decision.
  3. Resolve it with evidence: a small prototype, a benchmark on realistic data, a load test, a short design document, or a reversible rollout behind a flag. If the decision belonged to someone else, show that you made your case clearly and then committed to their call.
  4. Report the outcome fairly, including parts you got wrong. Use only numbers you actually measured. The weak version casts you as correct and the other person as stubborn, and ends with them agreeing.
  5. Connect it to pairing: the same habits (restate, compare against criteria, test the claim) are what you do when a partner suggests a different approach in a shared coding session.

Follow-up

  • What evidence would have changed your mind?
  • What if the person with decision authority had overruled you? What did you do next?
  • How was your working relationship with that person afterwards?

Share an example of a project where you took ownership from conception to deployment.

Medium · Behavioral and Background Questions

Approach

  1. Pick a project with a full arc: problem framing, design, build, test, release and operation. Give each stage a sentence or two and spend your time on two or three decisions, such as a scope cut, a technology choice with the alternative you rejected, or a rollout choice.
  2. Show the engineering around the code: the test strategy (unit, integration, contract), the release method (feature flag, canary, rollback plan), and the observability you added (dashboards, alerts, error budgets or the signals you watched in the first days).
  3. Cover what happened after launch: what broke or surprised you, how you found out, how you fixed it, and how you documented and handed it over. Ownership includes the on-call period, not just the merge.
  4. Be exact about I versus the team. Name collaborators, state your own pieces and report outcomes with figures you truly have (latency, error rate, cost, adoption). Sinking mistakes are stopping at shipped, or telling a coordination story with no technical decisions.

Follow-up

  • If you rebuilt it today, what would you change in the design?
  • How did you know it was working correctly in production?
  • What was cut from the original scope, and who disagreed?