Aurora Energy Research · Software Engineer
Updated · 2026-10-02

Aurora Energy Research Software Engineer
Interview Guide

THE 60-SECOND BRIEF

Candidates describe Aurora Energy Research as a company that builds energy research products for its clients. The Software Engineer role is reported as building applications that help users analyse energy markets and make decisions from the data, working beside product managers, data scientists and UX designers. The technologies candidates mention are JavaScript, TypeScript, Python, React, Node.js and AWS, with data visualisation tools and database systems listed as a bonus. The reported questions lean toward the browser side of that work, plus one system design question about real-time energy consumption data and one about API security.

This guide is for engineers with roughly two to four years of experience, the level candidates describe for this role, who are preparing for the Aurora Energy Research Software Engineer interview. It covers the two reported rounds, all fifteen reported questions grouped by type (JavaScript and React fundamentals, API handling in the UI, algorithms and caching, system design and security, and behavioral), and a seven-day plan.

Candidates report two rounds over about 2-4 weeks: an online screening, then an in-person interview with deeper technical questions, practical exercises and discussion of working style.

ReactState management & React lifecycleAPI integration (frontend)

36 min read

Browse Software Engineer questions

See the practice prompts

19Practice promptsAcross five skill areas

The reported question mix is weighted toward front-end engineering. The topics candidates name are React, state management and the component lifecycle, handling API calls in the front end, TypeScript and JavaScript. Expect to explain promises, compare TypeScript with JavaScript, say where state should live in a React app, and describe what you would do about a slow interface. Prepare each as a short spoken explanation backed by a code example you can write from memory.

Beyond the front end, the reported list includes an algorithm-improvement question for a data processing application, an array transformation function, an API response caching question, a design question about real-time processing of energy consumption data, and a question on API security for a data-intensive application. Those five reward a habit of stating input size, access pattern and failure behaviour before naming a tool. The role as candidates describe it analyses large energy datasets, so think in terms of volume, freshness and what the user sees while data loads.

The behavioral side is explicit in the reports: working with a UX designer, prioritising under deadlines, responding to feedback, handling pushback on a project, and a hard technical problem you solved. The in-person round is described as including discussion of working style, and the requirements mention cross-functional teamwork and code reviews. Build five or six real stories with numbers and reuse them across prompts.

Candidates list Python and Node.js as languages the role touches and AWS as cloud experience, so be ready to discuss a small service you built or deployed, even if the questions you meet stay in the browser. Domain knowledge of energy is described as nice to have, not required, so spend your time on engineering fundamentals instead of studying the sector.

01

Online Screening

reported

Candidates describe the online screening as a first check of your technical knowledge together with your own experience. The topics they name for the process as a whole are JavaScript, TypeScript, React, state management and API handling in the front end, so it makes sense to be fluent in those fundamentals before this stage. Prepare to define each concept plainly, show a small code example, and tie it to something you shipped.

What to demonstrate

  • Command of JavaScript and TypeScript fundamentals, such as promises, asynchronous error handling and the type system
  • Working knowledge of React state and component lifecycle behaviour
  • Ability to talk specifically about your own projects and what you personally built

How to prepare

  • Write a promise-based fetch helper from memory, then rewrite it with async and await, and explain how a rejection travels through each version
  • Prepare a two-minute account of one project: the stack, your contribution, and one decision you would change
  • List five differences between TypeScript and JavaScript and give a concrete bug that the type checker catches
Aurora Energy Research Software Engineer candidate reports ↗
02

In-Person Interview

reported

Candidates describe the in-person interview as deeper technical questions, practical exercises and conversation about how you work with others. Because practical exercises are reported, plan for writing working code live, not only explaining it. The technical areas on the reported list include algorithm improvement, array transformation, API response caching, real-time data processing design and API security, alongside the React and TypeScript topics.

What to demonstrate

  • Working code on a practical exercise, which a live coding format tests directly
  • Ability to reason about data-heavy design: ingestion, caching, API protection and failure behaviour
  • Collaboration and communication, since the stage is reported to include discussion of working style

How to prepare

  • Practise writing an array transformation function without autocomplete, then state its time and space complexity aloud
  • Sketch a pipeline for real-time consumption readings on one page: ingest, store, aggregate, serve, and what you cache at each point
  • Rehearse five behavioral stories on collaboration with design, prioritisation, feedback, pushback and a hard technical problem
Aurora Energy Research Software Engineer candidate reports ↗

PracHub editorial advice for the preparation topics above.

01

Answering the React state question with a list of hooks and no view on where state belongs

Organise the answer by placement: local state for one component, lifted state for siblings, context or a store for app-wide values, and a data-fetching cache for server data. Explain effect dependencies and cleanup when a component unmounts, then give one bug caused by getting each wrong.

02

Handling API errors only in a catch block and missing HTTP failures that do not throw

State that fetch resolves on 404 and 500, so you check the status and throw a typed error. Pair it with loading, error and empty states, cancellation of stale requests, and a rule for which calls may be retried.

03

Tuning UI performance by guesswork, such as wrapping everything in memoisation

Begin with measurement in the browser profiler, find the slow commit or large bundle, and then pick the fix: stable keys, virtualised long lists, memoising an expensive child, splitting code, debouncing input. Say what you measured before and after.

04

Giving a tool-name answer to the real-time energy data design and the API security question

For the design, ask about reading volume, how fresh results must be and how long data is kept, then describe ingest, storage, aggregation, serving and caching with failure behaviour. For security, cover authentication, authorisation per resource, input validation, rate limiting, transport encryption and avoiding leakage of internal data in errors.

05

Telling behavioral stories in 'we' language with no personal decision and no outcome

For each story, name what you personally decided, the trade-off, and a measurable result. Prepare separate stories for design collaboration, prioritisation, feedback, pushback and a hard technical problem, so one story is not stretched across all five.

Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.

15 technical prompts0 include a worked solution

How would you approach improving an inefficient algorithm in a data processing application?

medium
Problem-Solving / Case Studies

How would you approach improving an inefficient algorithm in a data processing application?

Approach
  1. Measure first. Profile the run (cProfile or py-spy for Python, the Node --prof flag or the DevTools profiler for JavaScript) on realistic data volumes to find the hot spot. Before touching anything, record a baseline time and a reference output to compare against.
  2. Look for algorithmic wins: a nested-loop lookup that is O(nm) becomes O(n+m) with a hash-map index. Sort once, not inside a loop. A rolling aggregate over a time series drops from O(nk) to O(n) with a sliding window or prefix sums. Watch for hidden quadratic patterns such as spreading an accumulator inside reduce.
  3. Fix data access: replace N+1 queries with one batched query, push filtering and GROUP BY into an indexed database, and in Python replace row-by-row loops with vectorised NumPy or pandas operations.
  4. Handle scale and memory: when data outgrows RAM, stream or chunk it. Only after the algorithmic fixes, parallelise the CPU-bound, partitionable parts with worker processes, and memoise repeated pure computations.
  5. Verify: diff the new output against the reference (with a tolerance for floating-point sums), re-run the benchmark, and report the speed-up alongside any memory cost.
Follow-up
  • The dataset no longer fits in memory. What changes?
  • How do you prove the faster version gives the same results when floating-point ordering changes the sums?
  • When is an algorithm with better big-O slower in practice?

Write a function to transform an array based on specific criteria.

medium
Coding / Algorithms

Write a function to transform an array based on specific criteria.

Approach
  1. Clarify the criteria and the contract first: the input element type, whether to mutate or return a new array, whether order must be preserved, and how to treat null, undefined or duplicate entries. Then write a couple of example inputs and outputs before coding.
  2. Choose the matching primitive: filter plus map for select-and-reshape, reduce into a Map or object for grouping (Object.groupBy in newer runtimes), a Set for deduplication (it keeps insertion order), flat(depth) for nesting, and a single loop for partitioning into two arrays.
  3. Keep it one O(n) pass where possible. Avoid reduce with a spread accumulator, which copies on every step and becomes O(n^2). If sorting is involved, it costs O(n log n), and Array.prototype.sort mutates in place (stable since ES2019), so copy first or use toSorted.
  4. When asked for O(1) extra space, transform in place with two pointers, for example moving all elements that match a predicate to the end while keeping the relative order of the rest.
  5. Test the edge cases out loud: an empty array, a single element, all or no elements matching, and sparse arrays (map and forEach skip holes).
Follow-up
  • Can you do it in place with O(1) extra memory?
  • How would you type this function generically in TypeScript?
  • What changes if the input arrives as a stream too large to hold in memory?

Track a rolling failure rate per destination for circuit decisions

easy
sliding windowring buffercircuit 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?

The plan follows the reported topic mix: JavaScript and TypeScript first, then React and UI performance, API handling and caching, system design and security, algorithms, and finally behavioral stories said out loud.

Small steps. Visible outcomes.0 / 7 completed
ONE WEEK · YOUR PACE

Prepare, practise & reflect

One practical outcome each day. Spend longer where you need it.

0 / 7 done
01Map the loop and audit your stack
  • Write the two reported stages, the online screening and the in-person interview, and note what each stage covers.
  • Rate yourself from 1 to 5 on JavaScript, TypeScript, React, Node.js, Python and AWS, the technologies candidates mention for this role.
  • Pick the three weakest areas and assign each to a day below.

Deliverable: A one-page loop map plus a rated skills list with three priority gaps named.

02JavaScript promises and TypeScript
  • Write a promise-returning function from memory, then convert it to async and await. Show how Promise.all, Promise.allSettled and Promise.race behave when one input rejects.
  • Write an unhandled rejection example and the fix, and explain the microtask queue ordering relative to setTimeout.
  • List the differences between TypeScript and JavaScript (static types erased at compile time, interfaces, generics, union narrowing, unknown versus any, strict mode) and write a snippet where the compiler catches a bug.

Deliverable: Working promise snippets and a one-page TypeScript versus JavaScript sheet with one compiler-caught bug.

Practice prompt ↗Practice prompt ↗
03React state, lifecycle and UI performance
  • Build a small component with useState and useReducer, lift state to a parent, and then move it to context. Note the re-render cost of each.
  • Write an effect with a dependency array and a cleanup function, and reproduce a stale-closure bug and the fix.
  • Take a long list with a slow filter and speed it up using keys, memoisation, virtualisation and code splitting. Record the profiler result before and after each change.

Deliverable: A small React sandbox with the state-placement variants and a before/after profiler note.

Practice prompt ↗Practice prompt ↗
04Calling APIs from the UI and caching responses
  • Write a fetch wrapper that checks response.ok, throws a typed error, supports AbortController, and retries only idempotent calls with backoff and jitter.
  • Render loading, error, empty and success states for it in a React component, with a Try again button.
  • Implement a response cache keyed by URL with a time-to-live, in-flight request sharing, and stale-while-revalidate. Note when ETag headers and invalidation after a write apply.
  • Practise the spoken version of the UI error-handling answer.

Deliverable: A fetch wrapper with an in-memory cache, a component showing all four states, and a spoken outline of the error-handling answer.

Practice prompt ↗Practice prompt ↗
05Data-heavy design and API security
  • Sketch the real-time energy consumption design on one page: ingest, buffering, storage, aggregation windows, serving and caching, with a note on late or duplicate readings.
  • Write a checklist for API security: authentication, per-resource authorisation, input validation, rate limiting, transport encryption, secrets handling and safe error messages.
  • Work through the PracHub practice exercise on listing latency that scales with page size, and relate it to pagination for large datasets.

Deliverable: A one-page design diagram, an API security checklist and a short note on pagination for large result sets.

Practice prompt ↗Practice prompt ↗Practice prompt ↗
06Algorithms and practical coding
  • Write the array transformation function in three variants (map and filter, reduce, in-place) and state the complexity of each. Cover empty input, duplicates and non-mutation.
  • Take a slow nested-loop data processing routine, profile it, replace the repeated lookups with a Map or Set, and note the new complexity.
  • Work through the PracHub practice exercise on a rolling failure rate per destination, which uses a sliding window.
  • Say the improvement story aloud as problem, measurement, change and result.

Deliverable: Three working array transforms with complexity notes, one before/after optimisation, and a spoken improvement story.

Practice prompt ↗Practice prompt ↗Practice prompt ↗
07Behavioral stories said out loud
  • Write five stories as situation, your decision, result and what you would change: a hard technical problem, pushback on a project, working with a UX designer, prioritising under deadlines, and feedback.
  • Say each story out loud and cut anything that does not show your own decision.
  • Add a number or a checkable outcome to every story and replace each 'we' with the part you did.

Deliverable: Five rehearsed stories, each with a personal decision and one measurable result.

Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗

Expand any day for tasks and deliverables. Your progress is saved on this device.

Candidates report behavioral prompts on collaborating with a UX designer, prioritising under deadlines, responding to feedback, handling pushback and solving a hard technical problem. The role is described as cross-functional with code reviews, so prepare stories about working with other disciplines, not only solo technical wins.

How do you handle errors from API calls in a user interface?

medium
Technical / Domain Questions

How do you handle errors from API calls in a user interface?

Approach
  1. Start by sorting failures by kind, because each needs a different response. A network failure or timeout is retryable. A 401 sends the user back through sign-in. A 403 means they lack permission. A 404 means the resource is gone. A 422 maps server validation messages onto form fields. A 429 means back off, honouring Retry-After if present. A 5xx is retried a limited number of times and then surfaced.
  2. Remember that fetch only rejects on network failure, so check response.ok (or the status) and throw a typed error; with axios-style clients the rejection already covers non-2xx. Model each request in the component as an explicit state: idle, loading, success, error, and show an empty state separately from an error state.
  3. Retry only idempotent requests (GET, PUT) automatically, using exponential backoff with jitter and a hard attempt cap. Do not auto-retry a POST unless it carries an idempotency key, and always offer a manual Try again button. Cancel in-flight requests with AbortController on unmount or when the inputs change, so a slow stale response cannot overwrite a newer one.
  4. Keep the user's context: preserve typed form input, keep the last good data on screen with an inline warning when a refresh fails, and fail per panel so one broken widget does not blank the whole page. Show a plain-language message, never the raw server text, and log the request id and status to monitoring. React error boundaries catch render errors only, not rejected promises or event handler errors, so say you use both.
Follow-up
  • Several requests fail with 401 at once because the token expired. How do you refresh it once and replay them?
  • How would you test the error paths without a real backend?
  • The same request is retried while the first one is still in flight and the user double-clicked submit. What prevents a duplicate write?

Can you describe a time when you had to collaborate with a UX designer? What was your approach?

medium
Behavioral / Leadership Questions

Can you describe a time when you had to collaborate with a UX designer? What was your approach?

Approach
  1. Choose a project where the designer's input changed what you built, and describe your approach as steps you took: joining before the design was final, asking what user problem each screen solved, and agreeing on shared vocabulary such as component names, spacing and states.
  2. Show the engineering contribution beyond implementing mockups. Examples include raising feasibility early (for instance a dense data table that would be slow to render, with a virtualised alternative), asking for loading, empty and error states, testing the design with realistic long labels and large datasets, and agreeing on a shared component library so the two of you did not diverge.
  3. Include one real disagreement and how it was settled with evidence, such as a quick prototype, a performance measurement or feedback from a user, not by seniority. Say what each side gave up.
  4. Close with the result in something checkable (shipped on time, fewer rework cycles, a usability issue found before release) and one thing you would change. The story that sinks this answer is one where the designer is cast as an obstacle, or where you only received specs and built them.
Follow-up
  • What did you do when the design could not be built in the time available?
  • How did you handle a change from design after development had started?
  • How do you check that what you shipped matches the design, including accessibility?

How do you prioritize tasks and manage deadlines in a fast-paced environment?

medium
Behavioral / Leadership Questions

How do you prioritize tasks and manage deadlines in a fast-paced environment?

Approach
  1. Open with the method, then spend most of the answer on a specific instance. Method: list the work, note for each item its deadline, who is waiting on it and what breaks if it slips, and rank by impact against effort. Re-rank when something new arrives instead of absorbing it silently.
  2. Use a concrete conflict from your own work, such as two urgent requests from different stakeholders. Say who you asked to decide the order (often the product manager), what you moved, and what you explicitly dropped or cut in scope. Cutting scope while keeping quality is a stronger story than working longer hours.
  3. Show communication: you flagged the risk before the deadline, offered options (smaller release now, the rest later) and confirmed the choice in writing. Mention protecting small recurring commitments such as code reviews so they do not pile up.
  4. Give the outcome with specifics (what shipped, when, what was deferred and what happened to it later). A weak version is a generic claim to be organised or a list of tools with no decision in it.
Follow-up
  • Which task did you say no to, and how did you tell the requester?
  • Two stakeholders both insist their request is the top priority. What do you do?
  • Your estimate turned out to be wrong halfway through. How did you handle it?

Tell us about a time when you received feedback. How did you respond?

medium
Behavioral / Leadership Questions

Tell us about a time when you received feedback. How did you respond?

Approach
  1. Pick feedback that was specific and a little uncomfortable, such as a code review pointing to unclear naming and missing tests, or feedback on how you communicated status. Avoid disguised compliments like working too hard, which show nothing.
  2. Describe your first reaction honestly and what you did with it: you asked a clarifying question, got an example, and checked whether the feedback was fair before deciding what to change. If you partly disagreed, say how you discussed it respectfully and what you took from it.
  3. Show the behaviour change: a concrete habit you adopted (a test checklist before opening a pull request, a short written update each day), not a vague intention to improve.
  4. Prove it worked with later evidence, such as fewer review comments of that type or a follow-up from the person who gave the feedback. Note that you now give feedback the same way. The answer fails when it is defensive or has no change afterward.
Follow-up
  • Tell me about feedback you disagreed with and what you did.
  • How do you give feedback to a peer in a code review?
  • How do you know the change stuck?
  • 01

    Can you describe a time when you had to collaborate with a UX designer? What was your approach?

  • 02

    How do you prioritize tasks and manage deadlines in a fast-paced environment?

  • 03

    Tell us about a time when you received feedback. How did you respond?

  • 04

    Provide an example of how you handled project pushbacks while working with a team.

  • 05

    Describe a challenging technical problem you faced and how you resolved it.

  • 06

    How do you handle errors from API calls in a user interface?

PracHub preparation framework ↗
How hard is the Aurora Energy Research Software Engineer interview?

Candidate reports put the difficulty somewhere between average and difficult, with a mix of technical, behavioral and problem-solving questions. The best preparation is to be able to explain the fundamentals (promises, React state, TypeScript) and also write short, correct code live.

Aurora Energy Research Software Engineer candidate reports ↗
How many rounds are there and how long does the process take?

Candidates report two rounds: an online screening followed by an in-person interview. The whole process is reported to take about 2-4 weeks, with news usually arriving within a few days of each stage.

Aurora Energy Research Software Engineer candidate reports ↗
Which technologies should I prepare?

The technologies candidates list for this role are JavaScript, TypeScript, Python, React and Node.js, plus cloud experience such as AWS. Data visualisation tools and database systems are described as nice to have. The reported questions concentrate on JavaScript, TypeScript and React, so put most of your time there.

Aurora Energy Research Software Engineer candidate reports ↗
Do I need energy-sector experience?

Candidates describe energy-sector or data-centric application experience as nice to have, not required. You can still prepare for the domain angle by treating the real-time energy consumption design question as a time-series ingestion problem: volume, freshness, aggregation, storage and caching.

Aurora Energy Research Software Engineer candidate reports ↗
What will the practical exercises in the in-person round look like?

Candidates mention practical exercises in that round but do not report a specific format. Prepare for writing real code live: an array transformation, an algorithm improvement and a caching mechanism are the coding-flavoured questions on the reported list. Practise in a plain editor and state complexity aloud.

PracHub Software Engineer practice ↗
How should I split a week of preparation?

Use the seven-day plan: JavaScript and TypeScript on day two, React and UI performance on day three, API calls and caching on day four, design and security on day five, algorithms on day six, and rehearsed behavioral stories on day seven. If you have the 2-4 weeks candidates describe, repeat the cycle with new examples.

Aurora Energy Research Software Engineer candidate reports ↗
Sources & methodology 3 sources ↗

No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.