Interview guides · Availity
Availity Software Engineer Interview Guide
Availity Software Engineer interview prep: five reported rounds, Java concurrency, SQL tuning, AWS design and X12/FHIR questions with worked approaches.
The 60-second brief
Availity runs a healthcare platform that links healthcare providers with health plans. Candidates describe Software Engineer work there as building, maintaining and migrating enterprise applications, revenue cycle solutions and the integration workflows that pass data between payers and providers. Day to day that means backend services and RESTful APIs, mostly in Java or C#, on relational databases (the reported questions name Oracle and Postgres), deployed to AWS through Git and Jenkins pipelines and monitored with Splunk and New Relic. Some teams also work on React frontends, high-volume data pipelines, or integrations built on the X12 EDI and FHIR healthcare standards, inside Scrum teams with product managers, UX designers and QA engineers.
This guide is for engineers applying to Software Engineer roles at Availity. The requirements candidates describe are a computer science or related degree, about four or more years of professional experience, strong Java or C#, SQL databases, RESTful services and hands-on AWS, plus Agile delivery with code reviews, unit testing, CI and Git. React or TypeScript, Docker and Kubernetes on EKS, Terraform or Ansible, and healthcare standards (HIPAA, X12, FHIR) are listed as advantages. The guide covers the five reported rounds, all 25 reported questions with worked approaches and follow-ups, a seven-day plan built on those questions, and the mistakes that cost points on these question types.
Candidates report five stages over about 4-6 weeks: Application Review, Recruiter Screening, an Automated Technical Assessment, a Technical Panel Interview with software engineers and technical leads, and a Managerial Conversation with engineering managers.
Focus areas
- Data Structures & Algorithms (DSA)
- Low-Level Design (LLD)
- High-Level Design (HLD)
Overview
The work candidates describe is integration-heavy backend engineering for healthcare: services and REST APIs that move eligibility, claims and authorization data between providers and health plans, running on AWS and backed by relational databases. The reported questions follow that work closely. You can expect Java language questions (abstract classes against interfaces, volatile and the atomic classes), a SQL tuning question against Oracle or Postgres, token-based authentication for REST services, test strategy, and a direct question about your experience with EDI, X12 or FHIR. Prepare each one as something you have done or would do on a real service, with a concrete example.
The coding questions candidates report are standard and short: reversing a linked list, validating brackets with a stack, two-sum in linear time, a string parsing and format-validation problem, and implementing a sort from scratch and comparing it with the built-in one. Those questions are easy to get mostly right, so the difference is in complete edge-case handling, stated complexity and clean code you can defend. Other example tasks candidates mention include an LRU cache, checking a string for unique characters without extra structures, and sorting parsed log entries by timestamp.
The depth sits in Java concurrency and design. Four reported questions cover producer-consumer with blocking queues or semaphores, volatile and atomics, a thread-safe scheduler or task queue, and backpressure in asynchronous pipelines, alongside a SOLID question that asks for a real project example. Be ready to write the code for these, not only define the terms. Candidates report that senior panels also go into system design: a highly available API gateway on AWS with EC2, VPC and Lambda, monitoring microservices with Splunk or New Relic, partitioning, indexing and replication for transactional databases, cloud security across IaaS, PaaS and SaaS, and moving a monolith component onto Amazon EKS.
The behavioral questions candidates report are about cross-functional disagreement, prioritising inside Scrum, refactoring inherited legacy code, mentoring junior developers, and why you want to work at Availity. Healthcare experience is listed as an advantage rather than a requirement, so if you lack it, learn the basic X12 transaction sets and FHIR resources well enough to talk about them accurately instead of bluffing.
The Availity interview process
The five rounds below are what candidates describe. Formats can differ by team, location and seniority, so ask your recruiter which assessment format and panel make-up apply to your loop.
Application Review
Candidates report an initial review of the application against the qualifications for the role. The requirements candidates describe are concrete: Java or C#, SQL databases, RESTful services, AWS, Agile delivery with Git, code reviews and CI, with React, containers on EKS, infrastructure as code and healthcare standards as advantages. Make those visible in the first lines of your resume with outcomes, not a skills list at the bottom. Candidates also report that visa sponsorship is typically not offered for these engineering roles, so check that your work authorization matches the posting before applying.
What to demonstrate
- Match between your experience and the listed stack: Java or C#, SQL, REST, AWS
- Evidence of Agile delivery: code reviews, unit testing, CI and Git workflows
- Any exposure to healthcare data standards such as HIPAA, X12 or FHIR
How to prepare
- Rewrite your top three resume bullets so each names a Java or C# service, the database or AWS component it used, and a measurable result.
- Add any X12, FHIR, EHR or HIPAA-regulated work explicitly; if you have none, show the closest integration or data-validation work you have done.
- Confirm your work authorization against the posting, since candidates report sponsorship is typically unavailable.
Recruiter Screening
Candidates describe a conversation with a recruiter about your background and the role. Use it to tell a short, consistent story that connects your backend, API and cloud work to the integration work this role involves, and to get the logistics you need for the rest of the loop. The motivation question (why Availity) is reported in the question bank, so have a specific answer ready here rather than improvising it later.
What to demonstrate
- Whether your background fits the role and its stack
- Your motivation for this company and this kind of healthcare work
- Logistics: location, timing and work authorization
How to prepare
- Rehearse a two-minute walkthrough of your career that ends on the service, API or migration work closest to payer-provider integration.
- Write your answer to the why-Availity question using its provider and health plan platform and a link to your own experience.
- Ask whether the coding assessment is a take-home or a timed online test, which languages it allows, and who sits on the technical panel.
Automated Technical Assessment
Candidates report a coding assessment at this stage, and mention both take-home assignments and timed online assessments in the pipeline. The reported coding questions (linked list reversal, bracket validation, two-sum, format parsing and validation, sorting) are the right practice set for this format; candidates do not report which ones appear here. Treat whatever you submit as code you will be asked about: candidates advise rereading the submission before the technical panel discusses it.
What to demonstrate
- Working, correct code that passes edge cases
- Time and space complexity of the chosen approach
- Readability: naming, structure and tests in what you submit
How to prepare
- Solve the reported coding questions timed in your strongest language, handling empty, single-element, duplicate and malformed inputs each time.
- For a take-home, include unit tests and a short README stating assumptions, complexity and what you would change with more time.
- Keep a copy of your submission and reread it before the panel, listing its weakest point and how you would fix it.
Technical Panel Interview
Candidates describe in-depth technical discussions with software engineers and technical leads. The reported question bank for this role spans Java language knowledge, SQL tuning, token authentication, testing, Java concurrency, low-level design and system design on AWS, and candidates report that senior panels go further into scalable, fault-tolerant system design. Prepare to write concurrency code, walk a query plan, and sketch an AWS architecture with its failure behaviour, and expect your assessment submission to come up.
What to demonstrate
- Depth in Java: language design, the memory model and concurrency primitives
- Design reasoning: SOLID, thread-safe components, and distributed systems on AWS
- Explaining trade-offs: indexing, partitioning, replication, monitoring and security choices
How to prepare
- Write a bounded producer-consumer with ArrayBlockingQueue and a clean shutdown, then a scheduler on a lock-guarded priority queue, and explain each line.
- Walk an EXPLAIN ANALYZE plan for a slow join in Postgres and say exactly which index you would add and why.
- Sketch a multi-AZ API gateway on AWS (Route 53, API Gateway or ALB, EC2 Auto Scaling, Lambda, private subnets) and state what happens when one AZ fails.
- Prepare one production debugging story using Splunk or New Relic, from alert to root cause to fix.
Managerial Conversation
Candidates describe a final conversation with engineering managers focused on cultural fit and alignment. The reported behavioral questions cover disagreement with a cross-functional partner or product manager, prioritisation inside Scrum, refactoring legacy code, mentoring, and motivation for joining Availity. Each answer should be one real story with your own decisions in it and a result you can state.
What to demonstrate
- How you work with product managers and cross-functional partners
- How you prioritise and handle changing requirements in Scrum
- Ownership of code quality and of other engineers' growth
How to prepare
- Write one STAR story each for disagreement, shifting priorities, legacy refactoring and mentoring, each with a measurable result.
- Prepare two questions for the manager about how their Scrum team handles technical debt and how it deploys to AWS.
- Rehearse the why-Availity answer so it names the provider and health plan platform and the part of it you want to work on.
Where candidates lose points
Saying volatile makes a shared counter thread-safe.
Separate visibility from atomicity before you are asked: volatile guarantees that other threads see the latest write, but count++ is still a read, an add and a write. Use AtomicInteger or LongAdder for counters, and a lock when an invariant spans more than one field.
Building producer-consumer or a task queue on an unbounded queue, with wait() inside an if and InterruptedException swallowed.
Use a bounded ArrayBlockingQueue so producers block instead of exhausting memory, which is also your backpressure answer. Guard any wait() in a while loop, restore the interrupt flag, and describe shutdown (one poison pill per consumer) without being asked.
Answering the slow-query question with "add an index" and nothing more.
Walk through the sequence: read the actual plan (EXPLAIN ANALYZE or DBMS_XPLAN), compare estimated and actual rows, check statistics and sargability, then choose a specific composite or covering index and say what it costs on writes.
An AWS gateway or EKS design that lists services but never says what happens when something fails.
For every component, state the failure case and the response: loss of an Availability Zone, Lambda concurrency limits, a slow downstream service, a bad deploy. Name the multi-AZ layout, health checks, throttling and rollback path.
Being unable to explain your own assessment code when the technical panel brings it up.
Candidates report take-home and timed assessments and suggest rereading your submission beforehand. Keep a copy, write down its complexity, its weakest part and what you would change, and be ready to extend it live.
Questions & practice
Write a program to reverse a linked list and explain the time and space complexity of your approach.
Medium · Data Structures and Algorithms
Approach
- Use the iterative three-pointer method: prev = null, curr = head; on each step save next = curr.next, set curr.next = prev, then move prev = curr and curr = next. Return prev as the new head.
- State the complexity: O(n) time and O(1) extra space, since each node is visited once and only pointers are rewired.
- Mention the recursive version (reverse the rest, then head.next.next = head and head.next = null). It is also O(n) time but uses O(n) call stack, which can overflow on a long list in Java.
- Test the edges out loud: an empty list, a single node, two nodes, and confirm the old head now points to null so no cycle remains.
Follow-up
- Reverse only the nodes between positions m and n.
- Reverse the list in groups of k nodes, leaving any final partial group as it is.
- How does the code change for a doubly linked list?
Given a string containing various types of brackets, write a function to determine if the input string is vali
Medium · Data Structures and Algorithms
Given a string containing various types of brackets, write a function to determine if the input string is valid using a stack.
Approach
- Use a stack and a map from each closing bracket to its opening one. Push opening brackets; on a closing bracket, fail if the stack is empty or its top is not the matching opener, otherwise pop.
- The string is valid only if the stack is empty at the end, so leftover openers such as "((" make it invalid.
- O(n) time and O(n) space in the worst case. An odd-length string can be rejected immediately.
- Clarify whether other characters can appear and whether they should be ignored, and test the empty string (valid), a string starting with a closer, and interleaving such as "([)]" (invalid).
Follow-up
- If there is only one bracket type, can you do it in O(1) space? (Yes, with a counter that must never go negative.)
- Return the index of the first invalid character instead of a boolean.
- What is the minimum number of brackets to remove to make the string valid?
How would you implement a sorting algorithm from scratch, and what are the performance trade-offs compared to
Medium · Data Structures and Algorithms
How would you implement a sorting algorithm from scratch, and what are the performance trade-offs compared to built-in sorting methods?
Approach
- Implement one well, for example merge sort: split in half, sort each half recursively, and merge with two pointers, taking from the left on ties so the sort is stable. It is O(n log n) in every case and uses O(n) extra memory.
- Compare the alternatives on the deciding properties. Quicksort is in-place and fast on average but O(n^2) in the worst case with poor pivots (use a random or median-of-three pivot) and is not stable. Heapsort is O(n log n) worst case with O(1) extra space but not stable. Insertion sort is O(n) on nearly sorted input and wins for very small arrays.
- Explain the built-ins: Java's Arrays.sort uses dual-pivot quicksort for primitive arrays and TimSort (stable, adaptive to existing sorted runs) for objects; Python's sort is TimSort-based. They are heavily tuned and tested, so writing your own is rarely the right production choice.
- Say when a custom sort is justified: counting or radix sort for bounded integer keys in O(n + k), or an external merge sort when the data does not fit in memory.
Follow-up
- How would you sort a 10 GB file of records with 1 GB of RAM?
- Why does Java use different algorithms for primitives and for objects?
- How would you change quicksort to cope with many duplicate keys? (Three-way partitioning.)
Can you solve a string manipulation problem involving parsing and validating specific format patterns?
Medium · Data Structures and Algorithms
Approach
- Pin down the format before coding: the exact characters allowed in each part, lengths, separators, whether whitespace or case varies, and whether you return a boolean, the parsed fields, or a list of errors.
- Choose the tool: an anchored regular expression (^...$, compiled once with Pattern in Java) for a simple flat format, or a hand-written scanner or small state machine when fields are nested or the error messages must say where parsing failed.
- Separate syntax from meaning: a date can match the pattern and still be invalid (February 30), and an identifier can have the right length and fail its check digit (a US NPI uses a Luhn check over the number prefixed with 80840).
- Run in O(n) over the string. Avoid nested quantifiers such as (a+)+ that can backtrack exponentially on hostile input.
- Test the empty string, whitespace at either end, zeros at the start of numeric fields, numeric overflow, and non-ASCII characters.
Follow-up
- Return every validation error in the input rather than stopping at the first.
- How would you process a file of millions of these records without loading it all into memory?
- Why can a regular expression be a denial-of-service risk, and how do you prevent it?
Given an array of integers, find two numbers such that they add up to a specific target number in linear time.
Medium · Data Structures and Algorithms
Approach
- Name the brute force first: check every pair, O(n^2) time and O(1) space.
- Use a hash map from value to index in one pass: for each element x, look up target - x; if present, return both indices, otherwise store x. That is O(n) time and O(n) space.
- Look up before inserting so an element is never paired with itself, and duplicates work correctly (for [3, 3] with target 6 the second 3 finds the first).
- If the input is sorted, or you can sort it and only need values, use two pointers from both ends: O(1) extra space, O(n log n) if you must sort first. State what you return when there is no solution.
Follow-up
- Return all unique pairs that sum to the target, without duplicates.
- Extend it to three numbers that sum to the target. (Sort, then two pointers for each element, O(n^2).)
- How would you support repeated queries over a stream of incoming numbers?
What are volatile and atomic keywords in Java, and what are the drawbacks of relying heavily on multithreaded
Medium · Low-Level Design and Concurrency
What are volatile and atomic keywords in Java, and what are the drawbacks of relying heavily on multithreaded synchronization?
Approach
- Clarify the terms: volatile is a Java keyword, but there is no atomic keyword; atomicity comes from the java.util.concurrent.atomic classes (AtomicInteger, AtomicLong, AtomicReference, LongAdder).
- volatile guarantees visibility and ordering: a write happens-before every later read of that field, and reads come from main memory rather than a stale cached value. It does not make count++ atomic, because that is a read, an add and a write.
- The atomic classes provide lock-free read-modify-write through compare-and-set (incrementAndGet, compareAndSet). Under heavy contention, LongAdder spreads updates across cells and scales better for counters.
- Drawbacks of heavy synchronization: contention that reduces throughput and raises tail latency, deadlocks from inconsistent lock ordering, and code that is hard to reason about. The alternatives are immutable objects, thread confinement and concurrent collections.
- Say where locks are still required: an invariant that spans two variables cannot be protected by two separate atomics.
Follow-up
- Why must the instance field be volatile in double-checked locking for a lazy singleton?
- What is the ABA problem with compare-and-set, and how does AtomicStampedReference address it?
- When is synchronized a better choice than an atomic variable?
Explain how backpressure works in asynchronous data processing pipelines and how you prevent memory overflow.
Medium · Low-Level Design and Concurrency
Approach
- Define the problem: when producers outpace consumers, an unbounded buffer between them grows until the process runs out of memory, and latency grows with it long before that.
- List the strategies: bound the buffer and block the producer (BlockingQueue.put), switch to pull-based demand where consumers request n items (the Reactive Streams request(n) model used by Project Reactor and RxJava), drop or sample when losing data is acceptable, or spill to a durable broker (such as Kafka or SQS) and let consumer lag absorb bursts.
- Choose by data type: claims or eligibility requests cannot be dropped, so block, or persist and process later; telemetry can be sampled.
- Across service boundaries, cap in-flight requests and concurrency per consumer, and return 429 or 503 with Retry-After instead of queueing without limit.
- Monitor queue depth, consumer lag and processing time, and alert on a lag trend rather than waiting for a memory alert.
Follow-up
- How does backpressure travel back across an HTTP call between two services?
- Which strategy would you choose for records that must never be lost, and why?
- Which metrics would show you that a pipeline is falling behind?
Can you explain how you would write an ad-hoc SQL query or optimize a slow-running query against an Oracle or
Medium · Technical and Domain Knowledge
Can you explain how you would write an ad-hoc SQL query or optimize a slow-running query against an Oracle or Postgres database?
Approach
- For an ad-hoc query, start from the grain of the answer, join outward from it, check each join for one-to-many fan-out before aggregating, use bind parameters, and run it against a replica or with a row limit rather than the primary.
- For a slow query, read the actual plan before changing anything: EXPLAIN (ANALYZE, BUFFERS) in Postgres, DBMS_XPLAN.DISPLAY_CURSOR in Oracle. Compare estimated with actual row counts; a large gap points to stale statistics (ANALYZE, DBMS_STATS).
- Look for full scans on large tables, nested loops over a big outer set, and sorts or hashes spilling to disk. Check sargability: a function on an indexed column, an implicit type cast, or a LIKE with a wildcard at the start all prevent index use.
- Fix with the least invasive change: a composite index with equality columns first and the range column last, a covering index (INCLUDE in Postgres), rewriting a correlated subquery as a join or EXISTS, or keyset pagination instead of a large OFFSET.
- State the cost: every index slows inserts and updates on a write-heavy transactional table, so verify the gain on the plan and the write path.
Follow-up
- An index exists on the filtered column but the plan ignores it. What are the possible reasons?
- How does the same query behave differently when it uses a bind parameter rather than a literal value?
- How would you add that index to a large production table without blocking writes? (CREATE INDEX CONCURRENTLY in Postgres, ONLINE in Oracle.)
Replace offset paging on the resource feed with keyset
Easy · keyset pagination · composite index · sort order
resource holds resource_id, tenant_id, owner_user_id, title, body_ref, version, status ('draft','active','archived','deleted'), created_at, updated_at, deleted_at, with an index on (tenant_id, status, updated_at DESC, resource_id DESC). The listing endpoint returns active resources for one tenant, newest update first, 50 per page, today with LIMIT 50 OFFSET n. Tenants reach page 400 and rows are created while they read. Write the keyset query, define what the cursor carries and how it is encoded, and say which part of the index each predicate uses. Assume PostgreSQL 16.
Approach
- Name the two failures separately. OFFSET 20000 makes the server produce and discard 20,000 rows, so page cost grows with depth rather than with page size. Independently, any write that changes how many rows sort above the offset moves the window between two fetches, and the direction decides which anomaly you get: an insert lands at the head of updated_at DESC and pushes already-returned rows down past the boundary, so they are returned a second time; a delete above the offset, or a row whose updated_at is bumped above the cursor, pulls rows up and one is never returned at all. Nothing in the response reveals either.
- Write the seek: WHERE tenant_id = $1 AND status = 'active' AND (updated_at, resource_id) < ($2, $3) ORDER BY updated_at DESC, resource_id DESC LIMIT 50. The row-value comparison is one index range rather than a disjunction, and both columns are NOT NULL, which is what makes that comparison well defined.
- Map each predicate onto the index: tenant_id and status are equality on the leading columns, (updated_at, resource_id) is the range, and the ORDER BY matches the index order so no Sort node appears and the scan stops after 50 rows. The DESC in the definition only matters for mixed directions — a plain ascending btree on the same columns is read backwards for this query.
- Put both sort columns in the cursor and nothing the client can tamper with into another tenant: base64 of (updated_at, resource_id), validated server-side, with tenant_id taken from the principal.
Follow-up
- The client asks for 'jump to page 400'. What do you offer instead, and what does the honest version cost?
- Sort order becomes user-selectable across four columns. How many indexes is that, and which would you refuse to add?
What are the primary differences between abstract classes and interfaces in Java, and when would you choose on
Medium · Technical and Domain Knowledge
What are the primary differences between abstract classes and interfaces in Java, and when would you choose one over the other?
Approach
- Lay out the mechanical differences: an abstract class can hold instance state, constructors and any access modifier, and a class can extend only one; an interface declares a contract a class can implement many of, with only public static final constants as fields.
- Cover modern Java: since Java 8 interfaces can have default and static methods, since Java 9 private methods, and since Java 17 sealed interfaces can restrict implementers. So the gap is now mainly state and constructors, not behaviour.
- Give the decision rule: use an interface for a capability shared by unrelated types (Comparable, Runnable, a PayerClient contract); use an abstract class when closely related types share state and a fixed algorithm skeleton, as in the template method pattern.
- Mention the default to prefer interfaces plus composition, since a class hierarchy locks you into single inheritance and couples subclasses to base-class internals.
Follow-up
- If a class implements two interfaces with the same default method, what does the compiler require and how do you call one of them? (Override it, and use InterfaceName.super.method().)
- Why can't an interface have a constructor, and how would you share initialisation logic instead?
- When would you replace an abstract base class with composition, and what does that cost?
What experience do you have working with healthcare data standards such as EDI, X12, or FHIR transactions?
Medium · Technical and Domain Knowledge
Approach
- If you have the experience, name the transactions you handled and your part in them: 270/271 eligibility inquiry and response, 276/277 claim status, 278 prior authorization, 837 claims, 835 remittance, and the 999 and TA1 acknowledgments.
- Show you understand the format: an ISA/IEA interchange envelope, GS/GE functional groups and ST/SE transaction sets made of segments and elements. Delimiters are declared in the fixed-length ISA segment, so a parser should read them from there rather than hard-code them.
- For FHIR, describe it as REST resources in JSON or XML (Patient, Coverage, Claim, ExplanationOfBenefit), mostly at version R4, with search parameters and SMART on FHIR using OAuth 2.0 for authorization.
- Tie it to handling: validate before processing, return clear rejections, write audit logs, and treat payloads as PHI under HIPAA (encryption, minimum necessary access, no PHI in logs).
- If you have no healthcare experience, say so plainly, then map the closest work you have done (file-based partner integrations, schema validation, idempotent processing) and show you have studied these formats.
Follow-up
- How would your parser behave if a partner sends a file with different delimiters or a malformed segment?
- How would you handle a batch where some claims are accepted and others rejected?
- How would you map an X12 270/271 exchange onto FHIR resources?
How do you structure unit tests and integration tests to ensure high software quality before pushing code to p
Medium · Technical and Domain Knowledge
How do you structure unit tests and integration tests to ensure high software quality before pushing code to production?
Approach
- Describe the layers: many fast unit tests (JUnit 5 with Mockito, dependencies injected through constructors so they can be replaced), fewer integration tests against real infrastructure, and a small number of end-to-end checks.
- For integration, use Spring Boot test slices (@WebMvcTest for controllers, @DataJpaTest for repositories) and a real database in a container (Testcontainers with Postgres) rather than an in-memory substitute whose SQL differs.
- Cover API boundaries with contract tests or stubbed partners (WireMock), so a change to a request or response shape fails in CI rather than in production.
- Wire it into the pipeline: unit tests on every commit in Jenkins, integration tests before merge, and coverage used to find untested branches, not as a target. Test the unhappy paths: malformed input, timeouts, duplicate requests.
- Name what you do about flaky tests: quarantine them, fix the root cause (shared state, timing, test order), and never retry them silently.
Follow-up
- How would you test code that calls an external payer API you cannot hit from CI?
- What would you deliberately not unit test, and why?
- A test fails one run in twenty. How do you find out why?
Walk me through the SOLID design principles and give an example of how you applied them in a recent project.
Medium · Low-Level Design and Concurrency
Approach
- Define each principle in one line with a concrete case: Single Responsibility (one reason to change), Open/Closed (add behaviour by adding classes), Liskov Substitution (a subtype must honour the base contract), Interface Segregation (small, focused interfaces), Dependency Inversion (depend on abstractions).
- Give a real before-and-after from your work, for example a service class that parsed, validated and persisted records split into three classes, with format-specific handling moved behind a strategy interface so a new partner format meant a new class and no edits to existing ones.
- Show an LSP violation you can recognise: a subclass that throws UnsupportedOperationException for an inherited method, or the classic Square that breaks Rectangle's setWidth contract.
- Connect Dependency Inversion to constructor injection in Spring, and say what it bought you: testing with mocks and swapping implementations.
- State the trade-off: applying every principle up front creates needless layers, so you refactor toward them when change actually arrives.
Follow-up
- When did applying one of these principles make the code worse?
- How is a dependency injection container related to the Dependency Inversion principle, and how is it different?
- How would you refactor a large service class that violates Single Responsibility without breaking callers?
How would you design a thread-safe scheduling system or task queue from scratch?
Medium · Low-Level Design and Concurrency
Approach
- Scope it first: one process or several, one-off or recurring tasks, whether tasks must survive a restart, and what happens when a task fails.
- In-process core: a min-heap (PriorityQueue) ordered by next run time, guarded by a ReentrantLock with a Condition. Workers wait with awaitNanos until the earliest task is due; inserting a task that becomes the new head signals the waiting workers. Insert and removal are O(log n). DelayQueue implements this pattern for you.
- Execute due tasks on a fixed worker pool so a slow task cannot block the scheduler thread. Recurring tasks re-enqueue with their next run time; failures retry with exponential backoff up to a limit, then go to a dead-letter list.
- Support cancellation (a flag checked before running, or removal by id) and a graceful shutdown that stops accepting tasks and lets running ones finish.
- Compare it with ScheduledThreadPoolExecutor, which you would use in practice. If tasks must be durable or shared across instances, store them in a table and claim them with SELECT ... FOR UPDATE SKIP LOCKED or a lease.
Follow-up
- How do you stop two instances of the service from running the same task?
- A task runs much longer than its interval. What happens to its next run?
- How would you make scheduled tasks survive a crash and restart?
How would you design a highly available API gateway architecture in AWS using services like EC2, VPC, and Lamb
Medium · System Design and Architecture
How would you design a highly available API gateway architecture in AWS using services like EC2, VPC, and Lambda?
Approach
- Clarify the inputs: request volume and burst pattern, latency target, whether callers are external partners or internal services, and the authentication model.
- Lay out the request path: Route 53, then Amazon API Gateway (or an Application Load Balancer) in front of compute across at least two Availability Zones in a VPC. The load balancer sits in public subnets; EC2 Auto Scaling groups and data stores sit in private subnets, with a NAT gateway per AZ.
- Use Lambda for spiky or lightweight handlers and as a token authorizer validating JWTs, and EC2 for steady, long-running or connection-heavy services. Note the trade-offs: Lambda cold starts and account concurrency limits against EC2 capacity planning.
- Add the edge controls: throttling and usage plans per client, AWS WAF, TLS everywhere, and health checks so unhealthy instances leave rotation. Keep instances stateless so any AZ can serve any request.
- State the failure behaviour: one AZ lost means the remaining AZs scale out; a full region outage needs a second region with Route 53 failover, with its cost and data replication trade-off made explicit.
Follow-up
- What happens to in-flight requests when an Availability Zone goes down?
- How would you rate-limit per partner, and where in the path does that limit live?
- How would you roll out a gateway configuration change without risking an outage?
What strategies do you use to monitor, log, and troubleshoot distributed microservices using tools like Splunk
Medium · System Design and Architecture
What strategies do you use to monitor, log, and troubleshoot distributed microservices using tools like Splunk or New Relic?
Approach
- Instrument first: structured JSON logs carrying a correlation or trace id that is propagated through request headers across services, metrics on rate, errors and duration (RED) per endpoint, and distributed tracing in an APM tool such as New Relic.
- Alert on symptoms tied to service-level objectives (error rate, p95 and p99 latency), not on averages or on every CPU spike.
- For an incident, follow a fixed sequence: scope it (which endpoint, which instances, since when, did it line up with a deploy), use traces to find the slow span, then check the dependency it points to: slow queries, connection pool exhaustion, thread pool saturation, GC pauses, or a downstream timeout.
- Use Splunk searches keyed on the trace id to follow one failing request across services, and compare a good time window with a bad one.
- In healthcare systems, mask or exclude PHI from logs, and close each incident with a fix plus a guard (a test, alert or limit) that stops a repeat.
Follow-up
- Latency spikes only at p99, a few times an hour. What do you check?
- Log volume is too costly to keep everything. What do you sample, and what must you keep?
- How do you set alert thresholds that catch real problems without paging people for noise?
How do you approach database partitioning, indexing, and replication strategies for large-scale transactional
Medium · System Design and Architecture
How do you approach database partitioning, indexing, and replication strategies for large-scale transactional workloads?
Approach
- Start from the access patterns: the main lookups, range queries, and the read-to-write ratio. Every design choice follows from them.
- Indexing: B-tree indexes for equality and range lookups, composite indexes ordered with equality columns before the range column, and partial indexes for hot subsets. Each index adds cost to every write, which matters on a transactional workload.
- Partitioning: range partitioning by date suits append-heavy transactional tables (for example by submission month), giving partition pruning and cheap removal of old data; hash partitioning spreads load evenly. Sharding across nodes on a key such as tenant makes cross-shard queries and transactions expensive, so choose the key that keeps most transactions on one shard.
- Replication: synchronous replication protects committed data at a latency cost; asynchronous replicas scale reads but lag, which breaks read-your-own-writes unless those reads go to the primary. Define the failover process and RPO and RTO targets.
- Name the hot-spot risk: a monotonically increasing key or one very large tenant can overload a single partition.
Follow-up
- One partition or shard is much hotter than the rest. What do you do?
- A user saves a record and immediately reads stale data. Why, and how do you fix it?
- How would you re-partition a large live table without downtime?
Can you explain how to secure cloud-based solutions across PaaS, SaaS, and IaaS layers?
Medium · System Design and Architecture
Approach
- Frame it with the shared responsibility model: on IaaS (EC2) you own the OS, patching, network configuration, application and data; on PaaS (RDS, Lambda, EKS control plane) the provider runs the platform and you own the application, configuration, identity and data; on SaaS you own identity, access settings and the data you put in.
- Controls that apply at every layer: least-privilege IAM roles instead of long-lived keys, MFA and SSO, encryption at rest with KMS and in transit with TLS, secrets in a secrets manager, and audit logging such as CloudTrail.
- Layer-specific controls: on IaaS, private subnets, security groups, patching and image scanning; on PaaS, hardened configuration, network isolation, and scanning container images; on SaaS, SSO with SCIM provisioning, data-sharing settings, and vendor review.
- For healthcare data, add HIPAA requirements: a business associate agreement with each vendor that handles PHI, access limited to what is needed, and audit trails on PHI access.
- Close with detection: configuration monitoring (for example, flagging a public S3 bucket or an open security group) and a tested incident response plan.
Follow-up
- An access key is leaked in a public repository. What do you do, in order?
- Who is responsible for patching the runtime when you deploy on Lambda?
- How would you detect a misconfigured storage bucket before data is exposed?
How would you migrate an existing on-premises monolithic application component to a containerized microservice
Medium · System Design and Architecture
How would you migrate an existing on-premises monolithic application component to a containerized microservices architecture on Amazon EKS?
Approach
- Use the strangler fig pattern: pick one component with a clear boundary and few shared tables, put a routing layer in front of the monolith, and move traffic to the new service in steps.
- Prepare the service for containers: a Dockerfile, configuration from environment variables and a secrets store, no local state, health endpoints, and logs written to stdout.
- Deploy on EKS with Deployments, Services, readiness and liveness probes, resource requests and limits, and a Horizontal Pod Autoscaler. Manage the cluster and infrastructure with Terraform and build images in the CI pipeline.
- Handle data last and carefully: share the database at first, then split ownership through change data capture or the outbox pattern, since dual writes without coordination drift. Account for latency over the on-premises link (VPN or Direct Connect) while the monolith remains.
- Shift traffic with a canary through the gateway or ingress, compare error rates and latency against the monolith path, and keep a one-step rollback ready.
Follow-up
- The new service still needs data that the monolith owns. How do you handle that during the transition?
- An operation that was one database transaction now spans two services. How do you keep it consistent? (A saga or outbox.)
- How would you measure whether the migration succeeded?
Every query on one table stalls for forty seconds mid-deploy
Medium · lock contention · ddl · migrations
During a release on PostgreSQL, every query touching resource times out for about 40 seconds and then recovers with no intervention. The release ran one migration, ALTER TABLE resource ADD COLUMN archived_reason TEXT, and the migration log shows it completing in 6 ms. Unrelated tables showed no change in error rate. Explain how a 6 ms statement caused a 40-second stall, give the ordered checks you would run on a live system to confirm it, and give the migration procedure that prevents a repeat.
Approach
- Separate the statement's duration from the lock's duration. ADD COLUMN with no default is a catalogue-only change and genuinely runs in milliseconds, but it requires ACCESS EXCLUSIVE, and it cannot acquire that until every transaction already touching the table has finished.
- Account for the queueing, which is the part that surprises people. A lock request that is waiting blocks later requests for conflicting modes behind it rather than letting them overtake, so one long-open transaction holds the DDL and the DDL holds all the traffic. The stall length is set by the longest open transaction, not by the size of the change.
- Confirm on a live system in this order: pg_stat_activity for that table ordered by xact_start, looking for the oldest transaction and specifically for state = idle in transaction; then pg_locks where granted = false to find the waiter; then join them on pid to name blocker and blocked. pg_blocking_pids() does that join for you and is the fastest single call.
- Prevent rather than merely time it better. Set lock_timeout to a second or two on the migration session so the DDL abandons the queue after a bounded wait and is retried, instead of holding it for as long as the oldest transaction lives. Be exact about what that buys: queries arriving during the wait still queue behind the pending ACCESS EXCLUSIVE request, so each attempt costs them up to one lock_timeout of added latency. The outage goes from 40 seconds to about one second per attempt, not to zero. Also run migrations away from deploy-time peaks, and put a statement timeout and an idle-in-transaction timeout on the analytics role that opens the long transactions.
Follow-up
- The same release also wants NOT NULL on that column. What is the sequence that gets there without a long lock?
- Your lock_timeout retry fails ten times in a row because the analytics transaction is always open. What do you change?
Suggested practice checklist
Each day works through one group of the 25 reported questions, starting with the coding the assessment needs, then Java design and concurrency, data and AWS design, and ending with the stories for the managerial conversation.
Day 1 — Core coding: linked lists, stacks and hashing
- Write iterative and recursive linked list reversal in Java and state the stack-depth risk of the recursive version.
- Write the bracket validator with a stack and test the empty string, a leading closer, "([)]" and leftover openers.
- Write two-sum with a hash map and with two pointers on sorted input, and compare their space use.
Deliverable: Three tested solutions, each with a comment stating its time and space complexity and the edge cases it covers.
Day 2 — Sorting and format parsing
- Implement a stable merge sort from scratch, then write a short comparison with quicksort, heapsort and Java's built-in sorts.
- Write a validator for a structured identifier with a check digit, returning every error rather than only the first.
- Write a parser that reads log lines, skips malformed ones and sorts the rest by timestamp.
Deliverable: A merge sort with tests, a one-page sorting comparison, a multi-error validator and a log sorter.
Day 3 — Java language, SOLID and testing
- Write a five-minute spoken answer on abstract classes versus interfaces, including default methods and the diamond rule.
- Refactor a class you wrote before so it follows Single Responsibility and uses a strategy interface, keeping the before and after versions.
- Write a test plan for one REST service covering unit tests, a Testcontainers integration test and a stubbed partner API.
Deliverable: A recorded Java answer, a before-and-after refactor to use as the SOLID example, and a test plan for one service.
Day 4 — Java concurrency
- Write producer-consumer twice, once with ArrayBlockingQueue and once with two semaphores and a mutex, each with a clean shutdown.
- Write a racing counter that fails with a volatile int, then fix it with AtomicInteger and with a lock, and explain each fix.
- Write a scheduler on a lock-guarded priority queue with awaitNanos, and write down three backpressure strategies and when each fits.
Deliverable: Two producer-consumer versions, a counter demonstration, a working scheduler and a written backpressure comparison.
Day 5 — SQL and data design
- Load a sample table into Postgres, write a slow join, read its EXPLAIN ANALYZE output and fix it with an index you can justify.
- Work the keyset-pagination practice question and explain why a large OFFSET degrades.
- Write a design for a claims-style transactional table covering indexes, date-range partitioning, replicas and read-your-own-writes.
Deliverable: A before-and-after query plan, a keyset pagination query and a one-page partitioning and replication design.
Day 6 — AWS, production and healthcare integration
- Sketch the multi-AZ API gateway with token authorization and throttling, and the EKS migration of one monolith component, each with failure cases.
- Write the step-by-step sequence you would follow for an intermittent latency spike, then work the debugging practice question about stalled queries during a deploy.
- Write short answers on JWT validation and OAuth flows, the shared responsibility model by layer, and the main X12 transaction sets and FHIR resources.
Deliverable: Two architecture sketches, a written incident sequence, and one-page notes on authentication, cloud security and X12/FHIR.
Day 7 — Managerial conversation and full rehearsal
- Write STAR stories for the disagreement, Scrum prioritisation, legacy refactoring and mentoring questions, each ending in a measurable result.
- Write and rehearse your why-Availity answer, tied to the provider and health plan platform and to your own work.
- Reread your assessment submission if you have one, and prepare two questions about technical debt and AWS deployment for the manager.
Deliverable: Four STAR stories, a rehearsed motivation answer, notes on your submission and two questions for the manager.
Behavioural preparation
Candidates report a final conversation with engineering managers about fit and alignment, and behavioral questions on cross-functional disagreement, Scrum prioritisation, legacy refactoring, mentoring and motivation. Prepare one real story for each, with your own decisions in it and a result you can state.
- Why do you want to work at Availity, and how do your professional values align with its mission in healthcare technology?
- Tell me about a production issue you debugged across several services, and what you changed afterwards.
How do you handle authentication and authorization in RESTful web services using tokens like JWT or OAuth?
Medium · Technical and Domain Knowledge
Approach
- Separate the two: authentication proves who the caller is, authorization decides what that caller may do. OAuth 2.0 is the delegation framework; a JWT is one token format it can carry.
- Pick flows by caller: authorization code with PKCE for a browser or React app, client credentials for service-to-service calls. The authorization server issues short-lived access tokens and rotating refresh tokens.
- Validate every JWT at the gateway or service: verify the signature against the issuer's JWKS keys (selected by kid), reject alg none and unexpected algorithms, and check exp, nbf, iss and aud.
- Authorize at two levels: scopes or roles from the token for the endpoint, and an object-level check in the service (can this provider see this member's record), since checking the token alone leaves broken object-level authorization open.
- Keep protected health information out of the token payload, because a JWT is only base64-encoded and signed, not encrypted, and send everything over TLS.
Follow-up
- How do you revoke a JWT before it expires? (Short lifetimes, a denylist keyed on jti, or opaque tokens with introspection.)
- Where should a React single-page app keep tokens, and what does that choice mean for XSS and CSRF?
- How does the caller's identity flow from the gateway to downstream microservices?
How do you implement the producer-consumer pattern in Java, and how do you handle thread safety using blocking
Medium · Low-Level Design and Concurrency
How do you implement the producer-consumer pattern in Java, and how do you handle thread safety using blocking queues or semaphores?
Approach
- Default to java.util.concurrent: a bounded ArrayBlockingQueue shared by producers calling put() and consumers calling take(). Both block when the queue is full or empty, so the bound itself gives you backpressure and thread safety without manual locks.
- Run producers and consumers on an ExecutorService and plan shutdown: send one poison-pill item per consumer, or interrupt the threads. On InterruptedException, restore the flag with Thread.currentThread().interrupt() and exit rather than swallowing it.
- Show the semaphore version: one semaphore counting empty slots (starting at capacity), one counting filled slots (starting at 0), and a mutex around the buffer. Acquire the slot semaphore before the mutex, or the code can deadlock.
- If asked for wait/notify, guard the wait() in a while loop (spurious wakeups, and another thread may have taken the item) and prefer notifyAll(), or use a ReentrantLock with separate notFull and notEmpty conditions.
Follow-up
- How do you shut the pipeline down without losing items already in the queue?
- When would you use offer() with a timeout instead of put()?
- With several consumers, what ordering guarantees remain, and how would you keep per-key ordering?
Can you describe a time when you had to resolve a technical disagreement with a cross-functional team member o
Medium · Behavioral and Culture Fit
Can you describe a time when you had to resolve a technical disagreement with a cross-functional team member or product manager?
Approach
- Pick a real disagreement about substance, such as scope against technical risk, a deadline against test coverage, or a shortcut against a durable design, where you were one of the people deciding.
- Situation and task in two sentences; spend most of the answer on actions: how you learned what the product manager needed and why, how you made the trade-off visible with data (estimates, risk, incident history), and the options you offered rather than a flat no.
- Show how it was settled: a joint decision, an experiment, or escalation with both views written down, and that you committed fully once it was decided, even if it went the other way.
- End with a measurable result and what changed in how you work with that partner. The answer fails if it casts the other person as wrong or if you won only through seniority.
Follow-up
- What would you have done if the decision had gone against you?
- What did you learn about the product manager's constraints that you had not known?
- Looking back, was the outcome right?
How do you prioritize your tasks and manage shifting requirements in a fast-paced Scrum environment?
Medium · Behavioral and Culture Fit
Approach
- Describe the actual mechanics: a sprint goal you protect, backlog refinement with the product owner, and ranking work by user impact, risk and dependency rather than by who asked loudest.
- Explain how you handle a mid-sprint change: you make the trade-off explicit to the product owner (this goes in, that comes out) instead of quietly absorbing it, and you split large stories so some value still ships.
- Back it with one concrete story: a requirement that changed during a sprint, what you dropped or deferred, and what was delivered.
- Mention what stops churn from recurring: clearer acceptance criteria, earlier spikes on unknowns, and raising risks at stand-up. Saying you simply work longer hours undermines the answer.
Follow-up
- A production issue lands in the middle of a sprint. What happens to the committed work?
- Tell me about a time you pushed back on a priority.
- How do you estimate work that has a lot of unknowns?
Tell me about a time when you inherited legacy code with technical debt and how you approached refactoring it.
Medium · Behavioral and Culture Fit
Approach
- Set the scene: what the code did, why it was risky (no tests, tight coupling, frequent defects), and why changing it mattered then, typically a feature that had to go through it.
- Show the sequence: characterization tests to pin current behaviour, finding seams to break dependencies, then small refactors each behind green tests and shipped separately, rather than a big-bang rewrite.
- Explain how you got time for it: tying refactoring to feature work in the sprint and showing the cost of leaving it (defect rate, change lead time).
- Give a measurable result (fewer defects, faster builds, a feature delivered sooner) and something you deliberately left alone. Blaming the original authors or describing an untested rewrite sinks the story.
Follow-up
- How did you convince the team or product owner to spend time on this?
- What broke during the refactor, and how did you find out?
- Which parts did you choose not to refactor, and why?
How do you approach mentoring junior developers and sharing knowledge across your team?
Medium · Behavioral and Culture Fit
Approach
- Name the mechanisms you use: pairing sessions, code review comments that explain the reason behind a request, design write-ups the junior engineer leads with your review, and handing over ownership of a component in steps.
- Tell one specific mentee story: where they started, what you did over weeks or months, and an observable result (they shipped a feature alone, took on-call, led a design review).
- Cover team-wide sharing: runbooks, short internal talks, and recording decisions so knowledge does not sit with one person.
- Show judgement about when to let someone struggle productively and when to step in. A generic "I am always available to help" answer with no example reads as no mentoring at all.
Follow-up
- Tell me about a mentee who was not improving. What did you change?
- How do you review a junior engineer's code without rewriting it for them?
- How do you know your mentoring is working?
Why do you want to work at Availity, and how do your professional values align with our mission in healthcare
Medium · Behavioral and Culture Fit
Why do you want to work at Availity, and how do your professional values align with our mission in healthcare technology?
Approach
- Base the answer on what the company does: a platform that connects healthcare providers with health plans, with revenue cycle and payer-provider integration work behind it.
- Link it to your own record: integrations, high-volume transaction processing, regulated data, or Java and AWS services that resemble the work this role describes.
- Show values through an example rather than adjectives: a time you cared about correctness for end users, or improved a process that wasted other people's time.
- Finish with what you want to build or learn in the role. Repeating mission language or saying only that healthcare matters will not land.
Follow-up
- What do you know about how providers and health plans use the platform?
- Which part of the role interests you most, and why?
- What are you looking for in your next team that you do not have now?