Interview guides · Alaska Airlines
Alaska Airlines Software Engineer Interview Guide
Alaska Airlines Software Engineer interview guide: six reported rounds, TDD and pair programming, Azure migration, SAML troubleshooting, 7-day plan.
The 60-second brief
Alaska Airlines is an airline, and the Software Engineer role described by candidates sits on the software side of it: digital products for guests and enterprise platforms used inside the company. The work candidates mention includes moving cloud-based APIs forward, Identity and Access Management systems, and building end-to-end custom applications in C# or Java, with Azure named as the cloud. Engineers are described as working in agile delivery teams next to product owners, designers and other developers, writing tests, reviewing code and mentoring junior engineers. For preparation, that means you should expect a mix of object-oriented coding, front-end work in React, architecture questions about migration and security, and conversations about how you work with other people.
This guide is for experienced Software Engineer candidates applying to Alaska Airlines. The requirements candidates describe are seven or more years of experience with n-tier applications in an object-oriented language such as C# or Java, cloud and distributed-systems experience, design patterns and SOLID, and the ability to mentor others; Identity and Access Management and high-availability operational work are listed as a plus. The guide covers the reported coding and front-end questions, architecture and cloud migration, troubleshooting and protocols, and the behavioral prompts, and it ends with a seven-day plan.
Candidates report six stages over roughly four to six weeks: a recruiter screen, a technical phone screen, a virtual onsite loop, technical interviews on architecture, a pair programming session and behavioral interviews.
Focus areas
- Test-Driven Development (TDD)
- React
- Flexbox
Overview
The reported questions fall into four groups. The coding group asks for hands-on construction: a seating allocation algorithm in C# or Java, a React to-do application or currency converter built live, and a question about unit testing and test-driven development under deadline pressure. The architecture group covers moving legacy APIs onto Azure, high-availability and fault-tolerant design, and securing authentication and authorization across tiers. The troubleshooting group covers a user locked out of a SAML-integrated application, the basics of enterprise network protocols, and diagnosing a bug or build failure while someone else watches. The behavioral group covers a recent project, motivation for the airline, and handling feedback and ambiguity. Some of the reported technical entries are broad topic statements rather than single questions, so prepare the underlying skill, not one rehearsed answer.
Two formats shape the preparation more than any single topic. First, candidates report a pair programming session, and reports also mention mob programming and test-driven development. You will be writing code with another person, so practise narrating decisions, writing the failing test first and accepting a different direction mid-stream without losing the thread. Second, the requirements describe seven-plus years of n-tier work, so design answers should show layers, boundaries and failure handling rather than a diagram of boxes. Pick your strongest C# or Java project and know its structure well enough to defend it.
The front-end questions are small and concrete: a React component built from nothing, CSS and Flexbox layout, and selecting elements inside native HTML inputs with CSS or JavaScript selectors. They are quick to practise and easy to lose points on if rusty, so give them their own sessions rather than assuming a back-end career covers them. Finish by rehearsing the behavioral prompts aloud, because leadership and cross-team collaboration are listed as the focus of the last stage.
The Alaska Airlines interview process
Candidates describe six stages across about four to six weeks. Treat the order and format below as reports from past candidates, and confirm the details your own loop will follow with your recruiter.
Recruiter Screen
The first conversation covers your background, what you expect from the role and how well you fit it. Candidates also describe it as a chance to talk about why you are interested in the company. Approach it as a short pitch: your strongest C# or Java experience, the kind of work you want next, and a real reason for choosing an airline's engineering team. It is also the right moment to ask how the later stages are run.
What to demonstrate
- Alignment between your background and the role
- Your expectations for the position
- Your interest in the company and why you chose it
How to prepare
- Write a three-part career narrative: early work, the project you owned, and what you want next, naming the languages and systems involved.
- Prepare an honest answer to why you want to write software for Alaska Airlines, tied to the work described in the role (cloud APIs, identity, guest-facing applications).
- Prepare questions about the rest of the loop: which stages are live coding, whether the pair session uses your own editor, and which language it expects.
Technical Phone Screen
Candidates describe a virtual conversation with an engineering manager or a senior engineer that focuses on full-stack experience and coding practices. A preliminary coding exercise or a deep dive into past technical work can appear at this stage. Prepare to take one real project from the browser to the data store and describe the testing you did along the way.
What to demonstrate
- Full-stack experience across front end and back end
- Everyday coding practices, including how you test
- How well you can explain your own past technical work
How to prepare
- Choose one full-stack project and prepare its story end to end: the React front end, the C# or Java service, the data layer and where tests sat.
- Be ready to explain your unit testing approach and what you do when a deadline squeezes it, which mirrors the reported question on TDD under tight deadlines.
- Keep a small coding warm-up fresh in C# or Java, for example the seating allocation problem, so a short exercise does not start cold.
Virtual Onsite Loop
Candidates report four to five sessions in the onsite, covering architecture, coding and behavioral topics. The loop lists technical interviews, a pair programming session and behavioral interviews as separate stages as well, so ask your recruiter which sessions sit inside the onsite and in what order. Plan for switching between design, code and personal stories on the same day.
What to demonstrate
- Architecture reasoning
- Hands-on coding
- Behavioral and collaboration skills across several sessions
How to prepare
- Run a back-to-back rehearsal: one design question, one live coding task and one set of behavioral answers in a single sitting.
- Rehearse the small front-end questions, such as selecting elements inside native HTML inputs with CSS or JavaScript, so they are quick when they appear between larger sessions.
- Prepare your design and behavioral material from the same project so the stories agree with each other.
Technical Interviews
These interviews are described as deep dives into architecture and system design. The reported architecture questions are about migrating legacy APIs onto Azure, designing highly available and fault-tolerant distributed systems, and securing authentication and authorization across a multi-tier architecture. Approach each by fixing scope first, then walking through layers, failure modes and the migration or rollout path.
What to demonstrate
- Architecture and system design reasoning
- How you explain architectural decisions
- Design of secure, layered enterprise applications
How to prepare
- Write a migration outline for a legacy API: inventory callers, put a gateway or facade in front, move one endpoint at a time, run old and new in parallel, and keep a rollback path.
- Prepare a high-availability checklist: redundancy across failure domains, health checks, timeouts, retries with backoff, idempotent operations and graceful degradation.
- Sketch an authentication and authorization flow across tiers (identity provider, tokens, service-to-service trust, role checks) and note where each check lives.
Pair Programming Session
Candidates describe pairing with someone on code, with attention to how you solve the problem as you go. Candidates also mention test-driven development and mob programming in connection with this stage. The reported coding questions (seating allocation, a React to-do application or currency converter, unit testing under deadline) are the natural practice material for a stage like this. Plan to think aloud, write tests first, and keep the code working while a partner suggests changes.
What to demonstrate
- Working code produced in a shared session
- Problem-solving approach as the solution evolves
- Communication while coding with another person
How to prepare
- Practise red-green-refactor out loud: write one failing test, make it pass with the least code, then refactor, and repeat for a currency converter.
- Build a React to-do application from an empty file twice, once with the design talk spoken aloud, then check CSS and Flexbox layout.
- Rehearse the moment a partner suggests a different approach: restate it, test it against the current constraint, then adopt it or explain why not.
Behavioral Interviews
The final stage is described as behavioral interviews centred on leadership and cross-team collaboration. The reported prompts ask about your communication style and past projects, a complex project you built and what you personally did, why you want to work for this airline, and how you handle feedback, ambiguity and real-time collaboration. Prepare specific stories in which you made the decisions.
What to demonstrate
- Leadership
- Cross-team collaboration
- Communication and ownership of your own contributions
How to prepare
- Write one story for each of the four reported behavioral prompts, each with your decision, its trade-off and a result you can defend.
- Prepare an example of working with product owners or designers, since the role is described as agile and cross-functional.
- Prepare a mentoring example, because mentoring junior engineers appears in the requirements candidates describe.
Where candidates lose points
Writing the whole implementation first and adding tests afterwards when the session is about test-driven development
Start with one failing test named for a behavior, make it pass with the least code, then refactor. Practise this on a currency converter until the red-green-refactor rhythm is automatic and you can narrate it.
Starting the seating allocation code before clarifying what a valid seating looks like
Ask what the rules are (adjacent seats for a party, cabin or row limits, what to do when a request cannot fit), state your assumptions, model seats and rows explicitly, and write tests for a full cabin and a party larger than any row.
Answering the legacy API migration question as a lift-and-shift or a big-bang rewrite with no cutover plan
Describe an incremental path: list the callers, put a facade in front, move one endpoint at a time, run old and new together, compare outputs and keep a rollback. Add how identity and access carry across.
Debugging the SAML sign-in failure by guessing instead of following a sequence
Reproduce the failure, decide whether it fails at the identity provider or the application, then inspect the assertion: audience and reply URL, signing certificate and expiry, clock skew, name identifier and attribute or group claims.
Telling behavioral stories in the plural, so your own contribution never becomes clear
Rewrite each story to separate what you decided, built and measured from what the team did, and prepare a values example (safety, doing the right thing, kindness) that shows an action you took.
Questions & practice
Test your command of core programming concepts, hands-on coding, and domain-specific implementation details.
Medium · Technical & Coding Foundations
Approach
- Treat this as a fundamentals check in your main language, C# or Java. Be able to explain value versus reference semantics: C# structs against classes, and the fact that Java passes object references by value. Explain why strings are immutable in both languages and why a StringBuilder belongs in a concatenation loop.
- Know your collections by cost. A Java HashMap or a C# Dictionary gives O(1) average lookup. A TreeMap or SortedDictionary gives O(log n) with ordered keys. An ArrayList or List<T> appends in amortised O(1) but inserts at the front in O(n). Pick the collection from how the data is accessed and say why.
- State the equality contract: objects that are equal must return the same hash code (equals/hashCode in Java, Equals/GetHashCode in C#). If you break it, a key goes missing from a hash map. Prefer immutable domain types, such as C# records or Java records, for keys.
- For implementation detail, model the domain explicitly (for example Flight, Seat and Booking types with enums for seat class) instead of passing raw strings and ints around. Write a unit test for each rule as you add it.
- Cover failure handling. Validate inputs at the boundary, throw specific exceptions rather than a catch-all, and in C# know that async/await does not create a thread by itself; it frees the caller while the I/O is pending.
Follow-up
- When would you choose an interface over an abstract class, and how does that relate to the SOLID principles?
- What happens to a HashMap entry if you mutate a field used in its key's hashCode after insertion?
- How would you make this class safe to use from multiple threads?
Write a C# or Java solution for an airplane seating allocation algorithm under time constraints.
Medium · Technical & Coding Foundations
Approach
- Clarify the model before coding: the seat map (rows by seat letters, aisle positions), whether a group must sit together in one row, whether an aisle may split a group, and what happens to seats already taken. A common version is the cinema-style problem: 10 seats per row, aisle after C and after G, groups of four.
- For the four-seat version, only rows that have reservations need work. Store them in a map from row to a bitmask of taken seats, and count 2 groups for every untouched row. For each reserved row, check the blocks B-E, D-G and F-I: if B-E and F-I are both free that is 2, otherwise 1 if any one block is free. This runs in O(k) for k reservations, not O(rows).
- For a general allocator, keep a 2D boolean grid or one bitmask per row and scan for the first contiguous free run of length n that does not cross an aisle. That costs O(rows x seats) per group. Seat the largest groups first (greedy) to reduce splits, and say plainly that a minimum-split allocation is a packing problem, so greedy is a heuristic.
- Write it as a small class (SeatMap with tryAllocate(groupSize) returning seat ids or empty) and add unit tests for: an empty plane, a full plane, a group larger than a row, a group that fits only across an aisle, and invalid seat labels.
- Name the concurrency gap: two agents can pick the same seat at the same time. In a real system that is closed with a unique constraint on (flight, seat) or optimistic concurrency on the row, not with an in-memory check alone.
Follow-up
- How would you change the allocator to honour window or aisle preferences without starving larger groups?
- Two bookings for the same seat arrive at the same moment: what guarantees only one succeeds?
- If no row can hold the whole group, how do you split it so members stay as close as possible?
Create a React to-do application or a currency converter component from scratch during a live session.
Medium · Technical & Coding Foundations
Approach
- Sketch the component tree first. For a task list: App holding the list state, an input form, and a TaskItem per entry. For a currency converter: amount input, from and to selects, a swap button and the result. Keep state in the lowest common parent and derive everything else (counts, filtered views, the converted value) during render instead of storing it twice.
- Use controlled inputs with useState and update immutably: add with setTasks(prev => [...prev, task]), toggle with map, delete with filter. Give every item a stable id as its key, not the array index, so deleting or reordering does not attach state to the wrong row.
- For the converter, pick one rate model and say which. Here: fetch a single table of rates against one base currency once, in a useEffect with an empty dependency array, and convert with amount * rate[to] / rate[from], where the base currency has rate 1. The effect then does not depend on the selected currencies, so changing a select recomputes during render without a refetch. Track loading and error states, and on cleanup either abort with AbortController or set an ignore flag so a stale response cannot overwrite newer state.
- Handle money and input edge cases. Keep the raw input as a string, reject empty and non-numeric values, and round only for display (toFixed or Intl.NumberFormat with a currency). Make swapping the two currencies and converting a currency to itself behave correctly.
- Lay it out with Flexbox (display: flex, gap, align-items: center) and write a couple of React Testing Library tests: adding a task renders it, and changing the amount updates the result with a mocked fetch.
Follow-up
- How would you persist the tasks across a page reload, and where would that side effect live?
- The user types quickly into the amount field: how do you avoid a request or an expensive recompute on every keystroke?
- When would you reach for useReducer or React.memo here, and what would each one change?
How do you implement robust unit testing and adhere to test-driven development (TDD) principles under tight de
Medium · Technical & Coding Foundations
How do you implement robust unit testing and adhere to test-driven development (TDD) principles under tight deadlines?
Approach
- Describe the red-green-refactor loop concretely. Write one failing test that names a behaviour, write the least code that passes it, then refactor with the tests green. Run the suite after every step, and never refactor while a test is red.
- Structure each test as Arrange-Act-Assert with one behaviour per test, and name it after the rule (for example Convert_ReturnsZero_WhenAmountIsZero). Use xUnit or NUnit in C#, and JUnit 5 with Mockito in Java.
- Make code testable by design. Inject dependencies through constructors so a fake or mock can replace the database, the HTTP client or the clock. Inject time instead of calling DateTime.Now or Instant.now() directly, so tests stay deterministic.
- Under a deadline, cut scope, not the test step. Test the business rules and boundaries first, keep most tests as fast unit tests with fewer integration tests above them, and leave cosmetic coverage for later. For untested legacy code, write characterization tests that pin current behaviour before you change it.
- Know where coverage numbers mislead: a line can be executed without its result being asserted. A suite only protects you if its assertions would fail when the behaviour changes.
Follow-up
- When is it reasonable not to write the test first, and how do you make up for it?
- A test passes locally but fails intermittently in CI: how do you find out why?
- How do you test code that calls an external rates or payment API without hitting the real service?
Can you explain how to select specific elements within native HTML inputs using CSS or JavaScript selectors?
Medium · Technical & Coding Foundations
Approach
- Use CSS attribute selectors to target inputs by kind: input[type="checkbox"], input[name="email"], input[type="text"][required]. Use state pseudo-classes for the rest: :checked (checkboxes, radios and options), :disabled, :focus, :focus-visible, :required, :valid and :invalid. Combine them with :not(), for example input:not([type="hidden"]).
- Know the limits of styling native controls. Their internal parts are only reachable through exposed pseudo-elements such as ::file-selector-button, or vendor-prefixed ones like ::-webkit-slider-thumb. accent-color recolours checkboxes and radios, and appearance: none removes native styling so you can build your own (while keeping it accessible).
- In JavaScript, document.querySelector returns the first match or null. querySelectorAll returns a static NodeList. getElementsByName returns a live NodeList and getElementsByClassName a live HTMLCollection, so those two change as the DOM changes. form.elements gives a form's controls by name.
- Read state from properties, not attributes. input.value is always a string (valueAsNumber exists for number inputs), and input.checked is the live state while the checked attribute only sets the default. Use CSS.escape when an id or name contains special characters.
- For many inputs, use event delegation: put one listener on the form and use event.target.matches('input[type="checkbox"]') or closest() to decide what was hit, rather than attaching a listener to each input.
Follow-up
- How would you style a custom checkbox while keeping it keyboard- and screen-reader-accessible?
- What is the difference between the value attribute and the value property after the user has typed?
- How would you select the label that belongs to a given input, in CSS and in JavaScript?
How do you isolate and resolve an unexpected runtime bug or build failure during a collaborative coding sessio
Medium · Troubleshooting & Protocols
How do you isolate and resolve an unexpected runtime bug or build failure during a collaborative coding session?
Approach
- Read the whole error before touching code. Find the first stack frame in your own code, the exception type and the message. For a NullReferenceException or NullPointerException, establish which reference is null and where it should have been set.
- Reproduce it as the smallest failing test, then fix against that test so it guards the bug afterwards. If it worked a few minutes ago, diff against the last green run. Across many commits, git bisect finds the change that introduced it in O(log n) steps.
- Treat build failures by kind. A compile error is fixed in code. Dependency resolution failures and version conflicts need dotnet restore, mvn dependency:tree or the Gradle dependencies task to see which version won. Stale artifacts need a clean build. Environment differences (SDK version, env vars) explain works-locally, fails-in-CI.
- In a pairing session, narrate one hypothesis at a time with the check that would disprove it, agree on the next step with your partner, and say what each result ruled out. Use a debugger breakpoint or a targeted log line rather than editing at random.
- After the fix, run the full suite, remove temporary logging, and name the root cause in one sentence, not just the line you changed.
Follow-up
- The test passes locally but fails in CI: what do you compare first?
- Your pair partner is convinced the cause is somewhere else: how do you decide whose hypothesis to check first?
- The bug only appears under load or intermittently: how does your approach change?
Write the update path that detects a concurrent edit
Medium · optimistic concurrency · transactional outbox · audit history
resource carries version INT NOT NULL DEFAULT 1. resource_revision holds revision_id, resource_id, version, actor_user_id, change_kind, patch JSONB, request_id, created_at with UNIQUE (resource_id, version). outbox_event holds aggregate_type, aggregate_id, aggregate_version, event_type, payload, status. A PUT carries the version the client read. Write the exact statements for the single transaction that applies the edit, records the revision and enqueues 'resource.updated', and give the handler's branch on zero affected rows. Then say what PostgreSQL 16 does under READ COMMITTED when two of these updates hit one row at once.
Approach
- One transaction, three writes, no network call inside it: UPDATE resource SET title = $3, version = version + 1, updated_at = now() WHERE resource_id = $1 AND tenant_id = $4 AND version = $2; then INSERT the resource_revision row at version $2 + 1; then INSERT the outbox_event row at the same aggregate_version. The event goes to a table rather than a broker because no transaction spans both.
- Branch on the affected-row count before doing anything else. Zero has three causes — stale version, wrong tenant, row gone — so re-read once and map to 409 carrying the current version, or 404 for an id outside the caller's tenant, which also stops the endpoint confirming that another tenant's id exists.
- State the engine behaviour instead of assuming it. Under READ COMMITTED the second UPDATE blocks on the row lock, and when the first commits PostgreSQL re-evaluates the WHERE clause against the newly committed row, so the version predicate now fails and the statement reports zero rows. Under REPEATABLE READ the identical collision raises SQLSTATE 40001 instead, so the handler must fold both shapes into one conflict response.
- Keep UNIQUE (resource_id, version) even though the predicate already serialises writers. It is what makes a lost update unwritable if any other path ever reaches the revision table, and it converts a logic bug into 23505 rather than into a silently missing history row.
Follow-up
- A client sends the version it read ten minutes ago and the resource has moved three versions. What is in your 409 so it can resolve the conflict without a full re-fetch?
- Two editors, two disjoint fields, no overlap. Does your answer still refuse the second write, and should it?
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
- 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.
- 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.
- 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.
- 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?
Evaluate your ability to design scalable systems, migrate legacy components, and handle complex enterprise dep
Medium · System Design & Architecture
Evaluate your ability to design scalable systems, migrate legacy components, and handle complex enterprise dependencies.
Approach
- Start with scope and dependencies. List the consumers of the legacy component, its downstream systems, its data stores and its traffic shape, then mark which dependencies cannot change on your schedule. Those set the migration order.
- Migrate with the strangler fig pattern. Put a facade or API gateway in front of the legacy system, move one capability at a time behind it, and route traffic to the new service per endpoint. Add an anti-corruption layer so the legacy data model does not leak into the new code.
- Design the new pieces to scale horizontally: stateless services behind a load balancer, a cache for hot reads, and a message queue between components that do not need a synchronous answer, so a slow consumer does not block the producer.
- Plan the data move explicitly: backfill, then keep both sides in sync with change data capture rather than ad-hoc dual writes, which can diverge when one write fails. Reconcile counts and checksums before you cut reads over.
- Protect against fragile enterprise dependencies with timeouts on every call, retries with exponential backoff and jitter for idempotent operations only, circuit breakers and bulkheads. Add tracing with a correlation id across old and new paths so you can compare them.
Follow-up
- The monolith and the new service both need the same table during the transition: how do you handle ownership?
- How do you roll back a capability that has already moved if the new service misbehaves?
- A downstream system enforces a strict rate limit: how does that change your design?
How would you approach migrating existing legacy APIs onto Azure cloud infrastructure?
Medium · System Design & Architecture
Approach
- Inventory first: every API, its consumers, its SLA, its auth scheme and its data and network dependencies, especially on-premises databases. Then choose a strategy per API: rehost (lift and shift), refactor or rearchitect, rebuild, or replace. Not every API justifies a rewrite.
- Put a gateway such as Azure API Management in front of the existing endpoints, so consumers keep a stable contract while you repoint individual operations from the legacy backend to the new one. That is the strangler pattern on Azure.
- Pick compute to match the API. App Service suits a web API being rehosted with few changes. AKS suits containerised services that need orchestration. Azure Functions suits event-driven or bursty endpoints. For SQL Server data, Azure SQL Managed Instance keeps closer compatibility than Azure SQL Database.
- Move secrets into Key Vault and use managed identities instead of connection strings in config. Reach on-premises systems over VPN Gateway or ExpressRoute, and watch chatty calls back on-premises, because each one now crosses that link.
- Cut over gradually. Run contract tests or shadow traffic to compare old and new responses, use App Service deployment slots or a weighted traffic split for canary releases, monitor with Application Insights, and keep the gateway route as the instant rollback.
Follow-up
- One API depends on an on-premises database that cannot move this year: what do you do?
- How do you prove the migrated API behaves the same as the legacy one before switching consumers?
- What would make you rearchitect an API instead of rehosting it?
What strategies do you use to design high-availability, fault-tolerant distributed systems?
Medium · System Design & Architecture
Approach
- Remove single points of failure. Run multiple stateless instances across availability zones behind a load balancer with health checks, and keep session state in a shared store or a token rather than in instance memory.
- Do the availability arithmetic. Dependencies in series multiply, so two services at 99.9% give about 99.8% together. Independent redundant copies combine as 1 - (1 - a)^n. That is why fewer synchronous dependencies and real redundancy both matter.
- Choose replication from RPO and RTO. Synchronous replication avoids data loss but adds write latency. Asynchronous replication is faster but can lose recent writes on failover. Active-passive is simpler to reason about, while active-active needs conflict handling.
- Contain failures. Use timeouts on every remote call, retries with exponential backoff and jitter only where the operation is idempotent (or carries an idempotency key), circuit breakers, bulkheads, and queue-based load levelling to absorb spikes. Degrade gracefully, for example by serving cached data when a dependency is down.
- Prove it works: test failover regularly, inject faults (kill instances, add latency), and alert on user-facing SLOs rather than CPU alone.
Follow-up
- During a network partition between two regions, how do you avoid split brain?
- Retries made an outage worse: why does that happen, and how do you prevent it?
- How would you test that failover actually works without waiting for a real incident?
How do you secure user authentication and authorization workflows across a multi-tier enterprise architecture?
Medium · System Design & Architecture
Approach
- Separate the two concerns. OpenID Connect authenticates the user and returns an ID token. OAuth 2.0 authorizes access and returns access tokens. Use the authorization code flow with PKCE for browser and mobile clients; the implicit flow is discouraged by current OAuth security guidance.
- Validate tokens at the edge and again in each service. Check the signature against the identity provider's published keys (JWKS), and check iss, aud, exp and nbf. Keep access tokens short-lived, with refresh token rotation, so a leaked token has limited value.
- For browser apps, prefer a backend-for-frontend that holds tokens server-side and gives the browser an HttpOnly, Secure, SameSite cookie, rather than keeping tokens in localStorage where any XSS can read them.
- Between tiers, use service identities: client credentials, mTLS or managed identities. When a downstream service needs the user's identity, use an on-behalf-of or token-exchange flow (RFC 8693) instead of forwarding the user's token unchanged.
- Make authorization explicit. Use roles or scopes in claims for coarse checks (RBAC) and attributes where rules depend on the data (ABAC), and always check object-level ownership in the service. Broken object-level authorization is the top item in the OWASP API Security list. Log every auth decision for audit.
Follow-up
- A user's access must be revoked immediately, but JWTs stay valid until they expire: what do you do?
- Where should a single-page app keep its tokens, and what attack does each option expose it to?
- How would you enforce that a user can only see their own bookings across three service tiers?
Assess your operational readiness, debugging methodology, and understanding of network and security protocols.
Medium · Troubleshooting & Protocols
Approach
- Scope before theorising. Find out who is affected (one user, one region, everyone), since when, and what changed (deploys, config, certificates, DNS, firewall rules). If users are hurting, mitigate first by rolling back or failing over, then find the cause.
- Walk the stack layer by layer, and let each check rule something out. Check name resolution with nslookup or dig, TCP reachability with nc or Test-NetConnection, and TLS with openssl s_client -connect host:443 -servername host (chain, expiry, SNI). Then check HTTP with curl -v and read the status code.
- Read status codes precisely. 401 means the request is not authenticated, 403 means authenticated but not allowed, 502 means the gateway got a bad response from upstream, and 504 means the gateway timed out waiting for upstream.
- Use observability. Follow one request's correlation id through logs and traces, compare error rates and latency before and after the change, and check that the instrumentation is healthy before trusting a missing signal.
- Close the loop on operational readiness: write a runbook entry for the failure, alert on user-facing symptoms, and run a blameless postmortem that names the fix that prevents a repeat.
Follow-up
- The gateway returns 504 but the service's own health check is green: where do you look?
- TLS handshakes fail intermittently for some clients only: what could cause that?
- What would you put in a runbook for this failure so someone else can handle it at night?
Walk through your troubleshooting steps when a user cannot access a SAML-integrated enterprise application.
Medium · Troubleshooting & Protocols
Approach
- Narrow the scope. Is it one user or everyone? SP-initiated or IdP-initiated login? Did anything change recently, such as a certificate rotation, a new app registration or a moved ACS URL? An everyone-fails pattern points at configuration; one-user-fails points at that user's account, group membership or attributes.
- Capture the exchange with a browser SAML tracer or a HAR file and decode the SAMLResponse (Base64 for the POST binding; requests on the Redirect binding are also DEFLATE-compressed). Check that the Status is Success.
- Validate the assertion field by field. The Issuer must match the expected IdP entity id, the Audience must match the SP entity id, and the Destination or Recipient must match the ACS URL exactly. NotBefore and NotOnOrAfter must hold, so check for clock skew. The signature must verify against the IdP's current signing certificate.
- Check identity mapping. The NameID format and value must match how the app looks the user up (an email change breaks this). The user must be assigned to the app in the IdP, and the group or role attributes the app uses for authorization must actually be present.
- Check the browser and app side last. If the app tracks the request in a cookie set with SameSite=Lax, that cookie is not sent on the cross-site POST back to the ACS; it needs SameSite=None; Secure. Then confirm the user is provisioned in the app and read the SP's own logs for the rejection reason.
Follow-up
- Login works for everyone except one user: what do you compare between their assertion and a working one?
- After the IdP rotates its signing certificate, every login fails: what was missed, and how do you avoid it next time?
- How does troubleshooting differ when the app uses OpenID Connect instead of SAML?
What are the foundational definitions and use cases of standard network protocols in an enterprise environment
Medium · Troubleshooting & Protocols
What are the foundational definitions and use cases of standard network protocols in an enterprise environment?
Approach
- Frame the answer by layer (link, network, transport, application) so every protocol has a place. IP routes packets, ARP maps IP addresses to MAC addresses on a local network, and ICMP carries diagnostics such as ping.
- Contrast TCP and UDP. TCP is connection-oriented, ordered and retransmitted, so HTTP/1.1, HTTP/2, SSH and SMTP run on it. UDP is connectionless and lower-overhead, so most DNS queries, DHCP, NTP and real-time media run on it. HTTP/3 runs over QUIC, which is built on UDP.
- Know the core services and ports. DNS is 53, using UDP and also TCP for zone transfers and large responses. DHCP is UDP 67/68 and leases addresses through Discover, Offer, Request, Acknowledge. HTTP is 80 and HTTPS 443, SSH 22, SMTP 25 (587 for submission), NTP 123 and SNMP 161.
- Cover the enterprise identity protocols. LDAP is 389 (LDAPS 636) and is used for directory lookups. Kerberos is 88 and issues tickets for Windows domain authentication. SAML and OIDC handle web single sign-on over HTTPS. Kerberos and signed SAML assertions both fail when clocks drift, which is why NTP matters.
- Explain what TLS adds: server authentication through a certificate chain, key exchange, and encryption. TLS 1.3 completes a full handshake in one round trip. Mention where TLS is often terminated (a load balancer or gateway) and what that means for traffic behind it.
Follow-up
- Walk through everything that happens on the network when a browser opens an HTTPS URL.
- Why does DNS mostly use UDP, and when does it fall back to TCP?
- If you terminate TLS at the load balancer, how do you protect the traffic between it and the services?
Suggested practice checklist
The seven days follow the reported loop: map the stages, then practise live coding and TDD, the front-end questions, architecture, troubleshooting, and finish with a full mock of the pair and mob sessions and behavioral answers.
Day 1 — Map the loop and write your stories
- List the six reported stages and ask yourself what each one needs: conversation, full-stack walkthrough, design, shared coding, behavioral.
- Write the career narrative and the answer to why you want to build software at Alaska Airlines, using the role's cloud, identity and guest-application work.
- Choose the one project you will use for the full-stack walkthrough and the complex-project question, and list its layers.
Deliverable: A one-page loop map, a written career narrative, a written motivation answer, and a project outline with its layers and your contributions.
Day 2 — Seating allocation with tests first
- Write down the rules and assumptions for a seating allocation problem in C# or Java, then model seats, rows and requests.
- Implement it test-first: failing test, minimal code, refactor, repeated for a single passenger, a group, a full row and an overflow request.
- Explain your unit testing approach for deadline pressure in a short spoken answer.
Deliverable: A working C# or Java seating allocator with its test suite, plus a spoken answer on TDD under deadlines.
Day 3 — React from an empty file
- Build a React to-do application from nothing, narrating each decision, with add, complete and delete.
- Build a currency converter component with controlled inputs, a rate lookup and test cases for invalid input and a zero amount.
- Lay out both components with CSS Flexbox and review state handling.
Deliverable: A to-do application and a currency converter component, each built twice, with the second run narrated and tested.
Day 4 — HTML inputs, selectors and CSS
- Write CSS and JavaScript selectors for native input elements by type, attribute, state and position, such as input[type='checkbox']:checked.
- Practise querySelector, querySelectorAll and label association on a small form, and note which selectors are brittle.
- Reinforce Flexbox: row and column direction, wrapping, alignment and flexible sizing.
Deliverable: A cheat sheet of tested selectors for native inputs, plus one Flexbox layout that you built from memory.
Day 5 — Architecture: migration, availability and security
- Outline the legacy API to Azure migration: inventory, facade, incremental cutover, parallel running and rollback.
- Write the high-availability checklist and apply it to a service with a database dependency.
- Sketch authentication and authorization across tiers (identity provider, tokens, service trust) and say where each check happens.
Deliverable: Three written design outlines (migration, high availability, authentication) with failure modes and trade-offs, and a spoken version of each.
Day 6 — Troubleshooting and protocols
- Write the SAML sign-in troubleshooting sequence and test it against failure causes such as expired certificate or clock skew.
- Summarize the common enterprise network protocols (DNS, HTTP and HTTPS, TLS, and others you use) and what each does in a login flow.
- Practise isolating a runtime bug or build failure while narrating, using a deliberately broken project.
Deliverable: A SAML runbook, a protocol summary with use cases, and a recorded narration of fixing a broken build.
Day 7 — Full mock: pairing, mob session and behavioral
- Run a mock pair session with a friend: one coding task test-first, with a requested change halfway through.
- Run a short mob rehearsal with three or more people: rotate the driver on a timer, let the navigators direct the work while the driver only types, narrate to the group and hand off half-finished code mid-test.
- Deliver the four behavioral stories aloud, including the project walkthrough and the feedback and ambiguity examples.
- Review the weakest answer from the week and rehearse it again.
Deliverable: A recorded mock pairing session, a mob rehearsal with at least one mid-test driver handoff, four rehearsed stories, and a list of fixes for your weakest answers.
Behavioural preparation
Candidates describe the last stage as behavioral interviews about leadership and cross-team collaboration, and the reported prompts also cover communication, ownership of a project, motivation and working with peers in real time. For a role that lists mentoring and agile delivery with product owners and designers, prepare stories where you made the decision, worked across roles and changed course in response to other people.
- Tell me about your communication style and a past project, and how both fit engineering and leadership values.
- Walk through a complex technical project you built recently and explain your specific contributions.
- How do you handle a situation where a peer suggests a different architectural approach mid-coding?
Explore your communication style, past project history, and alignment with engineering and leadership values.
Medium · Behavioral & Cultural Alignment
Approach
- Build the answer from three parts: a short career thread naming the languages and systems you worked on, one project where you owned a decision, and what you want to work on next. Concrete systems beat adjectives such as team player.
- Show your communication style through one episode, such as explaining a technical trade-off to a product owner or designer, and say what you changed after the first explanation did not land.
- Candidates report the airline's values as safety, doing the right thing, and being caring and kind. Do not recite them. Prepare a true example for each, such as pausing a release over a risk, owning a defect you introduced, or helping a colleague who was stuck.
- Connect the examples to the reported leadership theme: a time you led without authority, for example by driving a design discussion or cleaning up a testing practice across a team.
Follow-up
- Tell me about a time your communication failed and what you changed afterwards.
- Which of the projects you described would you build differently today, and why?
- Describe a time you disagreed with a leader and how you handled it.
Walk us through a complex technical project you built recently and explain your specific contributions.
Medium · Behavioral & Cultural Alignment
Approach
- Pick a project that matches the loop: layered or n-tier, in C# or Java, with tests and a production consequence. Set the scene in two sentences, then separate clearly what you built from what teammates built, using I for your decisions.
- Spend most of the time on one hard decision: the options you weighed, the trade-off you accepted, the evidence you used and what you rejected, for example a monolith versus separate services, or a synchronous call versus a queue.
- Cover how it was tested and released: unit and integration tests, how you rolled out, and what happened when something went wrong.
- End with a result you can defend and one thing you would change, and be ready to redraw the architecture from memory on a whiteboard or shared screen.
Follow-up
- Why that design instead of the alternative you mentioned?
- What broke after release, and how did you find it?
- Which part did someone else own, and how did you integrate with it?
Why do you want to build your career and write software specifically for Alaska Airlines?
Medium · Behavioral & Cultural Alignment
Approach
- Answer in three parts: what you understand about the engineering work (digital products, enterprise platforms, cloud API modernization, identity and access), where your own experience fits, and what you want to learn there. Take specifics from the job posting and recruiter conversations only.
- Give a true personal reason for working in aviation or travel software, such as reliability expectations, operational systems or user-facing booking flows. A reason that would suit any large employer is a weak answer.
- Link the reported values (safety, doing the right thing, being caring and kind) to something you have actually done, instead of repeating them back.
- Keep it short, say what you want in your first year, and do not claim knowledge of internal teams or systems that you cannot support.
Follow-up
- What do you know about the team you would join, and what would you want to learn about it?
- What would make you leave a role like this?
- Which other roles are you considering, and how does this one compare?
How do you handle feedback, requirements ambiguity, and real-time collaboration with peer developers?
Medium · Behavioral & Cultural Alignment
Approach
- Prepare three short stories, one for each part. For feedback, use a code review comment you disagreed with: say how you tested the claim, what you changed or defended, and what you took from it.
- For ambiguity, show a vague requirement you clarified: the questions you asked, the assumptions you wrote down, the smallest slice you built first and who confirmed it.
- For real-time collaboration, describe pairing or mobbing: narrating your thinking, trading driver and navigator roles, and what you did when a peer suggested a different architectural approach mid-coding (restate it, check it against the constraint, try it in a test, then commit).
- The mistake that sinks this answer is a story where you were right and everyone else was wrong. Show that you changed your mind at least once.
Follow-up
- What do you do when a peer's suggestion is clearly worse than your plan?
- Describe a time you changed your mind halfway through an implementation.
- How do you pair with someone far less experienced than you?