Interview guides · Allscripts
Allscripts Software Engineer Interview Guide
Allscripts Software Engineer interview guide: three reported rounds, C#, .NET and SQL Server questions, behavioral prompts and a seven-day plan.
The 60-second brief
Allscripts is described to candidates as a builder of healthcare software: electronic health record (EHR) platforms, practice management software and encounter systems used by providers, payers and patients. The Software Engineer role lists a .NET stack of C#, ASP.NET, WCF/WPF and SQL Server, with APIs and user interfaces for clinical workflows. Engineers work in Agile teams next to system analysts, product managers, database administrators and solution architects, and the listed duties include writing and testing C# code, reviewing peers' code, fixing production bugs and tuning queries and stored procedures.
This guide is for candidates applying to Allscripts as a Software Engineer, mainly on the C#, .NET and SQL Server side. It covers the three reported stages, the reported questions on object-oriented programming and .NET, databases and SQL, coding, web architecture and behavior, and a seven-day plan that turns them into practice.
Candidates report three stages over roughly 3-5 weeks: a Recruiter Phone Screen, an Online Assessment and Technical Evaluations. These are what candidates describe, not a published process.
Focus areas
- C# (.NET)
- Object-Oriented Programming (OOP)
- Basic Programming Concepts
Overview
The role centres on C#, the .NET Framework or .NET Core, ASP.NET and SQL Server, so the reported questions cluster around language mechanics and relational databases. They fall into five groups: object-oriented programming and .NET concepts (abstract class versus interface, garbage collection, sealed and static, throw versus throw ex), database and SQL questions (clustered versus non-clustered indexes, removing duplicate rows, normalization, ACID, joins and triggers), small coding problems, web architecture (SOA, WCF and REST, authentication, threads, logging) and behavioral prompts. Candidates are advised to explain why a keyword or structure is used, so rehearse each fundamental as a rule of choice plus an example, not as a definition.
The coding questions reported are short: reverse a string in place, pick a seat from a boolean array of occupied and empty seats, and test a prime or manipulate a matrix. Candidates describe writing on a whiteboard, in an online collaborative editor or on a machine coding problem, and are told to practise SQL and string or array code on paper or in a shared editor without IDE help. Problems this small are won on clarifying the input, listing edge cases, writing correct code by hand and stating time and space complexity, so practise away from autocomplete.
Two stages are easy to under-prepare. The Online Assessment is reported as mandatory for advancing and measures English communication as well as basic technical aptitude, so practise reading carefully and writing short, clear explanations. The managerial conversations in Technical Evaluations are reported to cover bugs and bottlenecks, changing requirements, disagreements, ownership outside your specialty and why you want to join. Prepare four or five true stories, and keep your resume accurate, because candidates mention background verification before onboarding.
The Allscripts interview process
Candidates report three stages across roughly 3-5 weeks. Technical Evaluations is the stage that bundles panels, coding tests and conversations with engineering managers.
Recruiter Phone Screen
Candidates report a first call that covers your work history, salary expectations and general fit with the role. Treat it as a structured conversation you can fully prepare: a short career story, a reason for this company, and logistics you have already decided.
What to demonstrate
- Work history and the projects you can describe credibly
- Salary expectations
- General alignment with the Software Engineer role
How to prepare
- Rehearse a two-minute walk through your CV that puts your C#, .NET and SQL Server work first, with one concrete project and your own part in it.
- Write a two-sentence answer to why Allscripts and why healthcare software that is true for you, using the product areas the role lists (EHR, practice management, encounter systems) only as far as you actually understand them.
- Decide your salary range, notice period and location constraints beforehand, and ask the recruiter how the remaining stages are run.
Online Assessment
Candidates report an assessment of English communication proficiency and basic technical aptitude, and say clearing it is required to advance. It comes before the technical panels, so use it to confirm the basics are fresh and your reading and pacing are steady.
What to demonstrate
- English communication proficiency
- Basic technical aptitude
- Careful reading of each question and time management
How to prepare
- Practise reading each question twice before answering, and time yourself so no single item eats the whole session.
- Refresh quick-recall fundamentals from the stack the role lists: the four OOP pillars, C# keywords such as static and sealed, and SQL join types.
- Write short, clear explanations of a few fundamentals, for example how an interface differs from an abstract class, since written clarity is part of what is measured.
Technical Evaluations
Candidates report technical panel interviews, either virtual or face to face, plus coding tests on a whiteboard, in an online collaborative editor or as a machine coding problem, and discussions with engineering managers and solution architects. This is where the reported OOP, .NET, SQL, coding, architecture and behavioral questions are practised.
What to demonstrate
- Working code for array, string and number problems, with edge cases and complexity
- Fluency in OOP, .NET and SQL Server fundamentals, including the reasons behind them
- Ability to explain design and service choices to managers and architects
How to prepare
- Hand-write the duplicate-removal query, a join comparison and a clustered versus non-clustered index explanation with no editor help.
- Do the reverse-a-string, seat-selection and prime-check problems aloud: restate the input, list edge cases, code, then state complexity.
- Prepare a comparison of SOA, WCF services and RESTful Web APIs, and an outline for authentication across distributed web applications.
- Have four or five behavioral stories ready for the manager and architect conversations, each with your own decision and a measurable result.
Where candidates lose points
Reciting a definition of abstract class versus interface, or value versus reference types, with no rule of choice
For each reported fundamental, prepare one sentence on when you would pick each option and a small example. For instance, an interface suits a capability many unrelated classes implement, while an abstract class suits related types that share state and default behaviour. Then say it aloud.
Writing a duplicate-removal query that deletes every copy, or has no tie-break for equal timestamps
Write it by hand with ROW_NUMBER() OVER (PARTITION BY the column ORDER BY a tie-breaking key), delete rows where the number is above 1, then test it on three or four sample rows that include ties and NULLs. Repeat for the join types and their NULL behaviour.
Starting to code the seat problem or the string reversal before pinning down the input
Ask what optimal means for the seats (farthest from any occupied seat, ties, all seats full, an empty row), and whether the string is a char array or an immutable C# string. List edge cases, code, then state time and space complexity.
Treating the Online Assessment as a formality
Candidates report it is required to advance and that it measures English communication as well as basic technical aptitude. Practise careful reading, pacing and short written explanations of fundamentals.
Behavioral stories told in the plural, with no personal decision and no result
For each of the five reported prompts, write a story outline in first person: the situation in two sentences, what you decided, what you measured, what you would change. A why-Allscripts answer that would fit any employer fails the same test.
Questions & practice
How does garbage collection work in.NET, and how do value types and reference types differ in memory allocatio
Medium · Object-Oriented Programming &.NET Concep
How does garbage collection work in.NET, and how do value types and reference types differ in memory allocation?
Approach
- Correct the common myth first. Reference-type instances live on the managed heap and the variable holds a reference. Value types are stored inline wherever they are declared: a local usually sits in the stack frame, but a struct field of a class sits inside that object on the heap, and array elements are stored inline in the array.
- Explain the generational collector. Allocation bumps a pointer in gen 0. A collection marks reachable objects from roots (stack locals, CPU registers, statics, GC handles), then compacts the survivors and promotes them to gen 1 and then gen 2. Most objects die young, which keeps gen 0 collections cheap.
- Cover the Large Object Heap. Objects of 85,000 bytes or more go there, are collected only with gen 2 and are not compacted by default, so large buffers allocated repeatedly cause fragmentation and gen 2 pressure.
- Name the hidden allocations. Boxing a value type to object or to an interface copies it to the heap. Assigning a struct copies it, so changing the copy leaves the original untouched.
- Separate memory from resources. The GC frees managed memory only. Connections and file handles need IDisposable with using. Finalizable objects survive at least one extra collection on the finalization queue, so call Dispose and GC.SuppressFinalize.
Follow-up
- How can a .NET application still leak memory, for example through event subscriptions or static collections?
- When would you make a type a struct rather than a class?
- What is the difference between workstation and server GC?
What is the difference between throw and throw ex inside a try-catch-finally block?
Medium · Object-Oriented Programming &.NET Concep
Approach
- throw; rethrows the exception currently being handled and keeps its original stack trace. throw ex; throws the same object again but resets the stack trace to the catch site, so the frame where the failure started is lost from the trace.
- throw; is only valid inside a catch block. To rethrow later, outside the catch (after collecting errors, or across a task boundary), use ExceptionDispatchInfo.Capture(ex).Throw(), which keeps the original trace.
- To add context, wrap instead: throw new DataAccessException("loading record 42 failed", ex). The original survives as InnerException and callers can catch the domain type.
- finally runs whether or not the exception is rethrown. If the finally block itself throws, the new exception replaces the one in flight, so keep cleanup in finally free of exceptions.
- Exception filters, such as catch (SqlException e) when (e.Number == 1205), handle only the cases you mean to handle, and an exception that does not match passes through without being caught and rethrown.
Follow-up
- How do you log an exception and still rethrow it without logging it twice further up?
- When is catching System.Exception acceptable?
- What does a caller see if a finally block throws while an exception is already propagating?
Write an optimal algorithm to reverse a string in-place without utilizing built-in high-level library function
Medium · Practical Data Structures & Coding Algor
Write an optimal algorithm to reverse a string in-place without utilizing built-in high-level library functions.
Approach
- State the constraint first: C# strings are immutable, so in-place means operating on a char[] (or Span<char>). Either the function takes a char[], or you call ToCharArray once and build one new string at the end.
- Use two pointers: i = 0 and j = n - 1, swap a[i] and a[j], then move them toward each other while i < j. That is n/2 swaps, O(n) time and O(1) extra space.
- Walk the edge cases aloud: null input, an empty array, length 1, and odd lengths, where the middle character stays in place.
- Use a temp variable or tuple swap ((a[i], a[j]) = (a[j], a[i])) rather than the XOR trick, which is harder to read and gains nothing.
- Give the Unicode caveat: reversing by char splits surrogate pairs (most emoji) and separates combining marks from their base letter. Reversing by text element (StringInfo) fixes that but is no longer in place.
Follow-up
- Reverse the order of words in a sentence in place.
- What does a recursive version cost in stack depth, and why avoid it for long input?
- How would you handle surrogate pairs correctly?
Write a program to check whether a given integer is a prime number or to manipulate a multi-dimensional matrix
Medium · Practical Data Structures & Coding Algor
Write a program to check whether a given integer is a prime number or to manipulate a multi-dimensional matrix efficiently.
Approach
- Prime check: return false for n < 2, true for 2, and false for other even numbers. Then trial-divide by odd d from 3 while d <= n / d. Writing the bound as division avoids d * d overflowing near int.MaxValue. That is O(sqrt n) time.
- For many queries up to N, use the Sieve of Eratosthenes: mark multiples of each prime p starting at p * p. It costs O(N log log N) time and O(N) memory, and a BitArray or an odds-only sieve cuts the memory.
- Matrix work: say which operation you are doing. To rotate an n x n matrix 90 degrees clockwise in place, transpose and then reverse each row, at O(n^2) time and O(1) extra space. Spiral order uses four shrinking boundaries (top, bottom, left, right).
- C# details: a rectangular int[,] uses GetLength(0) and GetLength(1), while a jagged int[][] can have rows of different lengths. Iterate in row-major order to keep cache locality.
- Edge cases: negative input, 0 and 1 for the prime check; empty, 1 x 1 and non-square matrices for the matrix tasks.
Follow-up
- How would you test primality for a 64-bit number quickly, for example with Miller-Rabin?
- Set a whole row and column to zero wherever a cell is zero, using O(1) extra space.
- How much memory does a sieve up to 100 million need, and how would you reduce it?
How do you establish and manage a secure connection to a database using an execution reader or data adapter?
Medium · Practical Data Structures & Coding Algor
Approach
- Open the connection safely. Read the connection string from configuration or a secret store, never from code. Prefer integrated or managed-identity authentication over SQL logins, set Encrypt=True with certificate validation (Microsoft.Data.SqlClient 4.0+ encrypts by default), and use a least-privilege database login.
- Put SqlConnection, SqlCommand and SqlDataReader in using blocks so they are disposed even when an exception is thrown. Disposing returns the connection to the pool, which is on by default and keyed by the exact connection string.
- Always parameterize: cmd.Parameters.Add("@id", SqlDbType.Int).Value = id. Never build SQL by string concatenation. AddWithValue can infer nvarchar for a varchar column, and the implicit conversion can stop an index seek.
- SqlDataReader is a connected, forward-only, read-only stream. It uses little memory but keeps the connection open while you read. SqlDataAdapter.Fill loads a disconnected DataTable or DataSet, opens and closes the connection itself if it was closed, uses more memory, and can push changes back through its Update method.
- On a web server, use the async methods (OpenAsync, ExecuteReaderAsync) so request threads are not blocked while waiting on I/O.
Follow-up
- What happens if readers or connections are not disposed under load, and what error appears when the pool runs out?
- Would you use a reader or an adapter to export a million rows, and why?
- How would you rotate the database password without downtime?
What is the difference between a Hashtable and a Dictionary in terms of thread safety, boxing, and lookup perf
Medium · Practical Data Structures & Coding Algor
What is the difference between a Hashtable and a Dictionary in terms of thread safety, boxing, and lookup performance?
Approach
- Typing and boxing: Hashtable (System.Collections) stores keys and values as object, so value types are boxed and every read needs a cast. Dictionary<TKey, TValue> is generic, avoids boxing for value types and catches type errors at compile time.
- Thread safety: Hashtable is documented as safe for multiple readers and one writer at the same time, and Hashtable.Synchronized wraps it for multiple writers. Dictionary allows concurrent reads only while nobody writes. Any writes need a lock, or use ConcurrentDictionary.
- Missing keys: the Hashtable indexer returns null, and the Dictionary indexer throws KeyNotFoundException. Use TryGetValue to avoid a double lookup and the exception.
- Lookup: both are average O(1) and degrade to O(n) with poor hash codes. Hashtable resolves collisions by double hashing and Dictionary by chaining entries within buckets. Dictionary is usually faster in practice because it avoids boxing and casts. Neither guarantees enumeration order.
- Key rules: Equals and GetHashCode must agree, and changing a key's fields after insertion makes the entry unreachable. Pass an IEqualityComparer such as StringComparer.OrdinalIgnoreCase for case-insensitive keys.
Follow-up
- Why can the factory passed to ConcurrentDictionary.GetOrAdd run more than once, and when does that matter?
- What happens if you modify a Dictionary while enumerating it?
- How would you write GetHashCode for a composite key?
What is the difference between a process and a thread, and how do you manage race conditions in multi-threaded
Medium · System Design & Web Architecture
What is the difference between a process and a thread, and how do you manage race conditions in multi-threaded programming?
Approach
- A process has its own virtual address space and handles and is isolated from other processes, so they communicate through IPC. A thread is the unit the OS schedules inside a process: threads share the heap and static data but each has its own stack and registers. Threads are cheaper to create and switch, and less isolated.
- Define a race condition: the result depends on how threads interleave. The standard example is count++, which is a read-modify-write rather than one atomic step, so two threads can lose an update.
- C# tools: lock (Monitor) around shared state on a private readonly object, Interlocked.Increment or CompareExchange for counters and flags, concurrent collections (ConcurrentDictionary, ConcurrentQueue), and immutable data. In async code use SemaphoreSlim.WaitAsync, because await is not allowed inside a lock block.
- Avoid deadlocks by taking locks in a consistent order, keeping critical sections small, using Monitor.TryEnter with a timeout where it fits, and never locking on this, a Type or a string. Note that volatile gives visibility but not atomicity.
- Mention races at the database level too: use optimistic concurrency with a rowversion column, or an atomic UPDATE ... WHERE that checks the state it expects.
Follow-up
- Why can't you await inside a lock, and what do you use instead?
- How would you track down a race condition that shows up only occasionally in production?
- When would you use a dedicated thread instead of the thread pool or Task.Run?
How do you write a SQL query to identify and eliminate duplicate rows from a table based on a specific column?
Medium · Database Architecture & SQL
Approach
- Find the duplicates first: SELECT col, COUNT() FROM t GROUP BY col HAVING COUNT() > 1, then join back to see the full rows before deleting anything.
- Delete while keeping one row per group: WITH d AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY col ORDER BY modified_at DESC, id DESC) AS rn FROM t) DELETE FROM d WHERE rn > 1. SQL Server lets you delete through a single-table CTE.
- Make the survivor deterministic. Add a unique tie-breaker such as id to the ORDER BY, and decide whether NULLs in the key count as duplicates of each other (PARTITION BY and GROUP BY both put them in one group).
- Make it safe on a large table. Run the SELECT version first, wrap the delete in a transaction and compare counts, and delete in batches (DELETE TOP (5000) in a loop) to keep log growth and lock escalation down. If child rows reference the losers through foreign keys, repoint them to the survivor first.
- Prevent the problem from coming back by adding a UNIQUE constraint or unique index on the column after cleanup. Without window functions: DELETE FROM t WHERE id NOT IN (SELECT MIN(id) FROM t GROUP BY col).
Follow-up
- How does the query change when duplicates are defined across several columns, such as name plus date of birth?
- How would you keep the most recently modified row instead of the oldest?
- What would you do if other tables reference the duplicate rows?
Explain the concept of database normalization (1NF through 3NF) and when intentional denormalization is accept
Medium · Database Architecture & SQL
Explain the concept of database normalization (1NF through 3NF) and when intentional denormalization is acceptable.
Approach
- 1NF: every column holds one atomic value, there are no repeating groups (phone1, phone2, phone3) and every row has a key. 2NF: 1NF and no non-key column depends on only part of a composite key. 3NF: 2NF and no transitive dependencies, so non-key columns depend only on the key.
- Use one worked example. In an order_items table keyed on (order_id, product_id), product_name depends only on product_id, which breaks 2NF, so it moves to products. Storing customer_city next to customer_zip in orders is a transitive dependency that breaks 3NF.
- State why it matters. Normalization removes update, insert and delete anomalies, such as changing an address in one row but not in the others.
- Denormalize deliberately, for measured read-heavy paths: reporting tables, a cached aggregate count, or an indexed view. Name the cost: you must keep the copy in sync through a trigger, a job or application code, and decide how stale it may be.
- Separate denormalization from history. Storing the unit price on an order line records the fact at sale time and is not redundant with the current product price.
Follow-up
- What does BCNF add over 3NF?
- How would you keep a denormalized total in sync, and what happens if the sync fails?
- Would you normalize a reporting warehouse the same way as the transactional database?
How do SQL transactions work, and what are the ACID properties in relational database systems?
Medium · Database Architecture & SQL
Approach
- A transaction groups statements into one unit: BEGIN TRAN, then COMMIT, or ROLLBACK on error. In T-SQL, use TRY/CATCH with SET XACT_ABORT ON so a runtime error rolls back the whole transaction, and check XACT_STATE() before committing.
- Atomicity: all or nothing, enforced through the transaction log. Consistency: constraints and rules hold before and after. Isolation: concurrent transactions see each other's changes only as far as the isolation level allows. Durability: once COMMIT returns, the change survives a crash because the log record was written to disk first.
- Know the SQL Server isolation levels and their anomalies: READ UNCOMMITTED (dirty reads), READ COMMITTED (the default), REPEATABLE READ (blocks non-repeatable reads), SERIALIZABLE (blocks phantoms) and SNAPSHOT, plus the READ_COMMITTED_SNAPSHOT database option that uses row versioning.
- Use a concrete example: moving an appointment means freeing one slot and booking another. Without a transaction, a failure between the two updates leaves the data inconsistent.
- Keep transactions short because locks are held until commit. When SQL Server picks a deadlock victim (error 1205), retry the transaction, and access tables in a consistent order to make deadlocks rarer.
Follow-up
- How do nested BEGIN TRAN calls behave in SQL Server, and what are savepoints for?
- What does SET XACT_ABORT ON change?
- When would you choose snapshot isolation, and what does it cost?
What is the difference between an abstract class and an interface, and when would you choose one over the othe
Medium · Object-Oriented Programming &.NET Concep
What is the difference between an abstract class and an interface, and when would you choose one over the other?
Approach
- Start with the mechanics. An abstract class can hold instance fields, constructors and implemented members with any access modifier, and a class can inherit only one class. An interface is a contract, and a class or struct can implement any number of them.
- Keep the answer current. Since C# 8 (.NET Core 3.0+), interfaces can carry default method implementations, static members and private helpers, but they still cannot hold instance fields or instance constructors. That shared-state limit is what still separates the two.
- Give a rule of thumb. Use an abstract class when closely related types share code and state, for example a template-method base with protected helpers. Use an interface for a capability that cuts across unrelated types (IDisposable, IComparable<T>) and for the seam you mock in unit tests or register in DI.
- Mention versioning. Adding a non-abstract member to a base class does not break derived classes. Adding a member to an interface breaks every implementer unless you give it a default implementation.
- Ground it in code: an abstract ExporterBase that owns formatting and file handling, and an IExporter interface that the rest of the code depends on.
Follow-up
- Can an abstract class implement an interface without implementing its members, and how?
- When would you use explicit interface implementation?
- Why not put default implementations in every interface instead of using abstract classes?
Explain the purpose and usage of the sealed and static keywords in C#.
Medium · Object-Oriented Programming &.NET Concep
Approach
- sealed on a class prevents inheritance (System.String is sealed). sealed on an override stops classes further down from overriding that virtual member again. Reasons to use it: protect invariants, signal that the type was not built to be extended, and let the JIT devirtualize some calls.
- A static class cannot be instantiated or inherited (the compiler emits it as abstract sealed) and can contain only static members. Extension methods must live in a non-generic static class.
- Static members belong to the type, not to an instance: one copy per type, and one per closed constructed type for generics, so Cache<int> and Cache<string> have separate static fields. A static constructor runs once before first use, and the runtime makes that run thread-safe.
- Give the trade-off for server code. Static mutable state is shared by every request thread, so it needs synchronization, and static calls are hard to replace in unit tests. A singleton registered in the DI container is usually the better choice for shared services.
Follow-up
- What happens to a type if its static constructor throws?
- Can a sealed class declare new virtual members, and can it override inherited ones?
- How would you unit test code that calls a static helper you cannot change?
Describe the concepts of polymorphism, encapsulation, and inheritance using a real-world software scenario.
Medium · Object-Oriented Programming &.NET Concep
Approach
- Pick one small domain and use it for all three ideas. For example, a notification module: an abstract Notification base with Send(), and EmailNotification and SmsNotification subclasses.
- Encapsulation: a Patient or Appointment class keeps its fields private and changes state only through methods that enforce invariants (Reschedule rejects a time in the past). It exposes read-only properties so callers cannot put the object into an invalid state.
- Inheritance: the base class holds the shared recipient, template and audit logic, and subclasses add only the transport-specific part. Explain the is-a test, and say you prefer composition (inject an ISender) when the relationship is really has-a.
- Polymorphism: a List<Notification> loop calls Send() and the runtime dispatches to the override through the virtual method table. Separate this runtime polymorphism from compile-time overloading, and show that new (method hiding) does not dispatch through a base reference while override does.
- Mention Liskov substitution. A subclass that throws NotSupportedException from an inherited method is a sign the hierarchy is wrong.
Follow-up
- What does a base-class reference call when the derived class hides a method with new instead of override?
- How does abstraction differ from encapsulation?
- How would you refactor a deep inheritance chain that has become hard to change?
What is the structural and performance difference between a clustered index and a non-clustered index?
Medium · Database Architecture & SQL
Approach
- Clustered index: a B-tree whose leaf level is the data rows themselves, stored in key order, so a table can have only one. A table without one is a heap. In SQL Server a PRIMARY KEY creates a clustered index by default if none exists yet.
- Nonclustered index: a separate B-tree whose leaf rows hold the index key plus a row locator, which is the clustering key on a clustered table or a RID on a heap. SQL Server allows up to 999 per table.
- Read performance: the clustered key suits range scans and ORDER BY on that key. A nonclustered seek that returns many rows needs a key lookup per row, so the optimizer may scan instead. A covering index with INCLUDE columns removes the lookups.
- Write cost: every index is maintained on INSERT, UPDATE and DELETE. A wide or random clustered key (a NEWID() GUID) causes page splits and fragmentation and makes every nonclustered index wider. Prefer a narrow, unique, ever-increasing key such as an IDENTITY column.
- Say how you would check: look for Key Lookup and Index Scan operators in the actual execution plan and compare logical reads with SET STATISTICS IO ON.
Follow-up
- Why might the optimizer ignore an index you added (non-SARGable predicate, function on the column, implicit conversion, low selectivity)?
- When would you use a filtered index?
- How would you choose the clustered key for a large table that is mostly appended to?
What are the differences between various types of database joins (INNER, LEFT, RIGHT, FULL OUTER), and how do
Medium · Database Architecture & SQL
What are the differences between various types of database joins (INNER, LEFT, RIGHT, FULL OUTER), and how do database triggers function?
Approach
- INNER JOIN returns only matching rows. LEFT JOIN returns every left row, with NULLs where nothing matches on the right. RIGHT JOIN is the mirror image. FULL OUTER JOIN returns every row from both sides. Draw a two-table example with one unmatched row on each side.
- Point out the classic trap: a WHERE filter on a right-table column turns a LEFT JOIN into an inner join because the NULL rows fail the filter, so that condition belongs in ON. Also note that NULL keys never match on equality and that a one-to-many join multiplies rows before any aggregate.
- Show an anti-join, rows with no match: LEFT JOIN ... WHERE r.id IS NULL, or NOT EXISTS. Avoid NOT IN against a column that can contain NULL, because one NULL makes the result empty.
- SQL Server triggers: AFTER (FOR) and INSTEAD OF triggers on INSERT, UPDATE and DELETE. They fire once per statement, not once per row, and read the inserted and deleted pseudo-tables (an UPDATE fills both). Code that assumes a single row is the common bug.
- Trade-offs: a trigger runs inside the caller's transaction, adds latency to every write, hides logic from readers of the application code, and can nest or recurse. Audit trails are a sound use; prefer constraints or explicit code for business rules.
Follow-up
- Write an AFTER UPDATE trigger that records old and new values for a multi-row update.
- How do LEFT JOIN with IS NULL, NOT EXISTS and NOT IN differ when the key column contains NULLs?
- When would you use an INSTEAD OF trigger on a view?
Given a boolean array representing occupied and empty seats in a row, write a function to find the optimal emp
Medium · Practical Data Structures & Coding Algor
Given a boolean array representing occupied and empty seats in a row, write a function to find the optimal empty seat nearest to an available open space.
Approach
- Pin down 'optimal' before coding. The common reading is to choose the empty seat that maximizes the distance to the nearest occupied seat. Ask about the tie rule (lowest index), what to return when every seat is taken (-1), and what to return when none is taken.
- Do one pass and track the last occupied index prev. For leading empty seats, sitting at index 0 gives a distance equal to the first occupied index. Between occupied seats at prev and i, the best seat is prev + (i - prev) / 2 with distance (i - prev) / 2 using integer division. For trailing empty seats, sit at n - 1 with distance n - 1 - prev.
- This runs in O(n) time and O(1) space. A simpler version to verify fills left-distance and right-distance arrays in two passes and takes the max of their minimum, at O(n) space.
- Test with an all-empty row, a single seat, occupied seats at both ends, adjacent occupied seats (gap of zero), and an even-length versus odd-length gap.
Follow-up
- People now arrive and leave over time. How would you pick each seat faster than O(n), for example with an ordered set of occupied seats or a priority queue of gaps?
- How would you seat a group of k people who must sit together?
- How does the approach change for a two-dimensional seating chart?
What design patterns have you implemented in production beyond standard MVC, MVP, or MVVM architectures?
Medium · System Design & Web Architecture
Approach
- Answer with two or three patterns you actually used, each as problem, then pattern, then consequence. A list of names without the problem they solved says little.
- Strong candidates: Strategy, to replace a growing switch over formats or rules with one class per variant chosen at runtime. Factory, to build the right strategy from configuration. Adapter, to put a legacy or third-party API behind your own interface. Decorator, to add caching, retry or logging around a repository without changing it.
- Show the C# shape: an interface, several implementations registered in the DI container, and the consumer depending only on the interface. Then say how this made unit testing or adding a new variant easier.
- Name the costs: more indirection and more types. Singleton in particular adds global state and makes testing harder, so prefer a DI singleton lifetime or Lazy<T>.
- Have one example where you decided a pattern was overkill and kept the simpler code.
Follow-up
- How is Strategy different from State?
- How did you test the code built around that pattern?
- How would you write a thread-safe singleton in C#?
Explain the differences between Service-Oriented Architecture (SOA), WCF services, and RESTful Web APIs.
Medium · System Design & Web Architecture
Approach
- SOA is an architectural style, not a technology: business capabilities exposed as services with explicit contracts and loose coupling, called over the network. WCF and REST are two ways to build such services.
- WCF is the .NET Framework stack for contract-first services ([ServiceContract], [OperationContract], [DataContract]) with interchangeable bindings: BasicHttpBinding (SOAP 1.1), WSHttpBinding (WS-Security, reliable messaging, transactions), NetTcpBinding (binary over TCP), named pipes and MSMQ. Metadata is published as WSDL, and configuration is heavy.
- A REST Web API (ASP.NET Core) models resources as URIs and uses HTTP verbs, status codes and usually JSON. It is stateless, works with HTTP caching, is easy for browsers and mobile clients, and is described with OpenAPI.
- Platform status: server-side WCF is not part of .NET Core or .NET 5+. CoreWCF is the community port, and WCF client libraries are still available. gRPC is the usual modern replacement for NetTcp-style internal calls.
- Choose by need: keep WCF or SOAP where existing enterprise clients or WS-* features depend on it. Use REST for new web, mobile and partner APIs. To migrate, put a REST facade in front and run both until the clients move.
Follow-up
- How would you move a WCF service to ASP.NET Core without breaking existing clients?
- How do you version a REST API?
- Which HTTP methods are idempotent, and why does that matter for retries?
How do you implement secure user authorization and authentication across distributed web applications?
Medium · System Design & Web Architecture
Approach
- Separate the two terms: authentication establishes who the caller is, and authorization decides what that caller may do. Then centralize authentication in one identity provider instead of having each app keep its own users.
- For users, use OpenID Connect sign-in with the OAuth 2.0 authorization code flow, plus PKCE for SPAs and mobile apps. Each API validates the JWT access token without calling back to the provider: signature against the provider's JWKS keys, issuer, audience and expiry.
- For authorization, express roles and claims as ASP.NET Core policies ([Authorize(Policy = "...")]) and also check access to each resource on the server (may this user open this record?). Hiding a button in the UI is not access control.
- Token handling: short-lived access tokens plus refresh tokens that can be revoked. In browsers, store tokens in HttpOnly, Secure, SameSite cookies rather than localStorage, which XSS can read. Use TLS everywhere and the client-credentials flow or mTLS between services.
- For local accounts, hash passwords with PBKDF2, bcrypt or Argon2, offer MFA, and record an audit log of who accessed sensitive records.
Follow-up
- How do you revoke a JWT before it expires?
- What are the trade-offs between server-side sessions and bearer tokens?
- How do you prevent CSRF when the token sits in a cookie?
How do you approach error handling and logging across multi-tiered healthcare platforms?
Medium · System Design & Web Architecture
Approach
- Set a policy per layer. Catch an exception only where you can recover or add context. Translate at boundaries: the data layer turns SqlException into a domain exception, and global middleware in the API layer maps exceptions to HTTP status codes with ProblemDetails. Clients never see stack traces.
- Use structured logging with message templates (Microsoft.Extensions.Logging, Serilog or NLog). Give each request a correlation ID, or the W3C traceparent, and pass it through every tier and queue message so one request can be followed end to end in a central log store.
- Keep patient data and secrets out of diagnostic logs. Log record IDs, not names, dates of birth or clinical content, and keep the access audit trail separate from application logs.
- Log each failure once, at the layer that handles it; logging and rethrowing at every layer produces duplicates. Reserve Error for actionable failures and alert on error rates rather than on single lines.
- Handle transient faults with retry, exponential backoff and jitter (for example Polly), but only for idempotent operations. Add a circuit breaker for a failing dependency and a dead-letter queue for messages that keep failing.
Follow-up
- How would you trace one failed request across a web tier, a service and the database?
- What would you never write to a log in a system that handles patient records?
- How do you stop retries from creating duplicate writes?
Listing latency scales with page size, not with filters
Easy · n+1 · latency · query batching
The tenant listing endpoint reads resource filtered by tenant_id and status, ordered by updated_at DESC, and returns each row plus the owner's display name from app_user and the actor of that resource's latest resource_revision. p99 is 55 ms at 10 rows per page and 1.4 s at 200. Database telemetry shows 401 statements per request, each under 1 ms, and nothing in the slow-query log. Diagnose the cause and give the fix, stating the statement count per request and the p99 you expect afterwards.
Approach
- Read the counters before forming a theory. 401 statements for 200 rows is one driver query plus two per row, and sub-millisecond execution with an empty slow-query log rules out a bad plan. The time is round trips, which is why it is invisible in every per-query metric and scales with rows returned rather than with filter selectivity.
- Name the two per-row statements from their normalised text: a single-row app_user lookup by user_id, and a resource_revision lookup by resource_id ordered by version DESC LIMIT 1. Confirm by dropping those two response fields and watching the statement count fall to one. That locates the calls in the serialisation layer, not the repository.
- Check that the arithmetic accounts for the whole gap. Measure one round trip to the replica in isolation; 400 trips at roughly 3 ms of network plus 0.2 ms of execution is about 1.3 s on top of a 55 ms baseline, which matches. If the multiplication had fallen short, the N+1 would only be part of the story and you would keep looking.
- Batch both lookups. Collect owner_user_ids and resource_ids from the driver query, then issue WHERE tenant_id = $1 AND user_id = ANY($2) for the users, and PostgreSQL's SELECT DISTINCT ON (resource_id) ... WHERE resource_id = ANY($2) ORDER BY resource_id, version DESC for the latest revision, which the UNIQUE (resource_id, version) index serves directly. On an engine without DISTINCT ON, use a lateral join or a row_number window. Three statements per request at any page size.
Follow-up
- The page size is capped at 200 today. What breaks first if it is raised to 2,000, and is it still this bug?
- How do you stop the next N+1 from reaching production, given that no individual query is slow and the endpoint's tests pass?
Suggested practice checklist
The plan follows the three reported rounds and the question groups candidates report for the C#, .NET and SQL Server stack. Each day ends with something written or spoken that you can check.
Day 1 — Map the loop and script the recruiter call
- Write out the reported sequence: Recruiter Phone Screen, Online Assessment, Technical Evaluations, and mark which one you are least ready for.
- Write and time a two-minute career walkthrough that leads with your C#, .NET and SQL Server work.
- Write your answer to why you want to join Allscripts and how your goals fit, using only facts you can verify.
Deliverable: A one-page loop map, a timed career walkthrough script and a written why-Allscripts answer.
Day 2 — C# and object-oriented fundamentals
- Write when you would choose an abstract class and when an interface, with one code example of each.
- Explain sealed and static with an example of each, then show in code why throw preserves the original stack trace and throw ex resets it.
- Describe polymorphism, encapsulation and inheritance using one real software scenario, with a virtual and override example.
Deliverable: Written answers and code snippets for the abstract class versus interface, sealed and static, throw versus throw ex, and OOP scenario questions.
Day 3 — .NET runtime, collections and concurrency
- Outline garbage collection generations and how value and reference types are allocated, including a value type held inside an object, and where IDisposable fits.
- Make a comparison table of Hashtable and Dictionary on boxing, thread safety and lookup, and write when you would use a concurrent collection.
- Write a short race-condition example and fix it two ways, then write a connection example using a using block, a parameterised command and an execution reader.
Deliverable: A one-page runtime and collections cheat sheet and two code samples: a race condition with its fix, and a safe database read.
Day 4 — SQL by hand
- Explain clustered versus non-clustered indexes, including key lookups and the write-cost trade-off, in a diagram on paper.
- Write the duplicate-removal query two ways, ROW_NUMBER with a delete and a GROUP BY on the minimum key, and test each on sample rows with ties.
- Write one example of each join type, a short normalization walk through 1NF to 3NF with one justified denormalization, an explicit transaction with rollback, and an AFTER INSERT trigger.
Deliverable: A handwritten SQL sheet with index diagram, both duplicate queries, join examples, a normalization example, a transaction and a trigger.
Day 5 — Coding without an IDE
- Reverse a string in place with two pointers on a char array, in a plain editor, then state time and space complexity and what changes for an immutable string.
- Solve the seat-selection problem on a boolean array: write your interpretation of optimal, handle all-full, empty-row and edge-seat cases, and check with a single pass.
- Write a prime check with trial division up to the square root, then a matrix task such as a rotation or transpose, listing edge cases before coding.
Deliverable: Three solutions written without autocomplete, each with an edge-case list and a stated complexity.
Day 6 — Web architecture and service design
- Write a comparison of SOA, WCF services and RESTful Web APIs, and when you would pick WCF over ASP.NET Web API.
- Outline authentication and authorization across distributed web applications: where tokens are issued and validated, how roles are checked, and what happens on expiry.
- List two design patterns you have used in production beyond MVC, MVP or MVVM, and design the error handling and logging for a multi-tier application, including correlation identifiers and keeping sensitive patient data out of logs.
Deliverable: A one-page comparison of SOA, WCF and REST, a token flow diagram, and a two-pattern and logging outline.
Day 7 — Behavioral stories and a full spoken run
- Write outlines of five stories for the reported behavioral prompts, each with the situation in two sentences, your decision, a measured result and one thing you would change.
- Run a timed spoken pass of your weakest five technical questions from days 2 to 6, then fix the answers that wobble.
Deliverable: Five written story outlines, a recorded or timed spoken pass, and a list of the answers still to fix.
Behavioral stories for Allscripts
Candidates report that the conversations with engineering managers cover how you handle a hard bug, shifting requirements, disagreements, ownership beyond your specialty and why you want to join. For a role built on C# and SQL Server, choose stories where you made a technical decision and can say what you measured. Prepare four or five true stories and map each to a prompt.
- Why are you interested in joining Allscripts, and how do your technical background and career goals align with the company's mission?
Describe a challenging bug or performance bottleneck in a previous project and how you diagnosed and resolved
Medium · Behavioral & Managerial Leadership
Describe a challenging bug or performance bottleneck in a previous project and how you diagnosed and resolved it.
Approach
- Choose a bug or bottleneck you personally diagnosed, ideally on a C#, .NET or SQL Server system, so the technical detail is easy to defend. A story where you only watched a teammate fix it will not hold up.
- Narrate the sequence: the symptom and who felt it, how you reproduced it, how you narrowed it down (logs, profiler, a query execution plan showing a scan where a seek was expected), the hypothesis you tested, then the fix.
- Quote only numbers you really measured, before and after, such as response time or rows read. If you have none, say what you observed and how you confirmed the symptom was gone.
- Close with what stopped it recurring (a regression test, an index, an alert) and one thing you would do differently. Skipping the evidence and jumping straight to the fix is the usual way this answer fails.
Follow-up
- How did you confirm that your change, and not something else, caused the improvement?
- What else did you rule out, and how long did you chase a wrong lead?
- What did you add so the same problem would be caught earlier next time?
How do you handle changing requirements or tight deadlines when working on enterprise deliverables?
Medium · Behavioral & Managerial Leadership
Approach
- Pick one concrete episode in which requirements moved or a date tightened on a deliverable with several stakeholders. Name the change and when you learned of it.
- Show the triage in order: clarify what changed and why, estimate its effect on scope and date, then bring options to the product owner or analyst (cut scope, move the date, accept named risk) instead of silently absorbing it.
- Say what you refused to give up, such as unit tests or code review on the risky part, and what you deferred in writing. In an Agile team, say what moved out of the sprint to make room.
- Finish with the outcome and the lesson. Stories that are only overtime and heroics, or that blame the stakeholder, tend to sink this answer.
Follow-up
- What did you cut or postpone, and who agreed to it?
- How early did you tell stakeholders the date was at risk?
- What would you do differently if the same change arrived tomorrow?
Give an example of a situation where you had a technical disagreement with a team member and how you reached a
Medium · Behavioral & Managerial Leadership
Give an example of a situation where you had a technical disagreement with a team member and how you reached a resolution.
Approach
- Choose a real technical disagreement with a peer, such as a stored procedure versus application logic, a schema choice, or sync versus async calls. A trivial or invented disagreement is easy to see through.
- State both positions fairly, including the strongest argument for the other side, before saying what you argued. This shows you understood the trade-off, not only your own preference.
- Explain how it was settled with evidence instead of seniority or persistence: a small prototype, a benchmark, a look at the execution plan, or a decision by the owner of the component.
- Report the result honestly, including a compromise or the case where you were wrong, and show the working relationship afterwards. Painting the colleague as the problem is the mistake that sinks it.
Follow-up
- What would you have done if the evidence had been inconclusive?
- Have you changed your mind in a disagreement like this, and what changed it?
- How did you handle it once the decision went against you?
Why are you interested in joining Allscripts, and how do your technical background and career goals align with
Medium · Behavioral & Managerial Leadership
Why are you interested in joining Allscripts, and how do your technical background and career goals align with our mission?
Approach
- Build the answer in three parts: why healthcare software draws you, what in your background matches the role, and what you want to grow into. The question asks about background and career goals as well as the company, so do not answer only the first part.
- For the match, name the stack the role lists (C#, .NET, ASP.NET, SQL Server) and one project where you used it, with your part in it. Mention the reported areas (EHR, practice management, encounter systems) only as far as you understand them.
- Speak about the company's mission only in terms you read in its public material and can repeat accurately. Praise that would fit any employer, or claims you cannot support, weaken the answer.
- Tie the goal to the work: for example, going deeper on service integration or on database performance. Keep it to a short answer you can give in under a minute.
Follow-up
- What do you think is different about building software where data accuracy and uptime affect patients?
- Which part of the stack would you want to own first?
- Where do you want to be after a year in this role?
Tell me about a time when you had to take ownership of a feature outside your immediate area of expertise.
Medium · Behavioral & Managerial Leadership
Approach
- Pick a feature you owned end to end that sat outside your strongest area, such as a C# developer taking a stored procedure, a reporting query or a front-end screen. Make clear you were accountable for the result, not a contributor.
- Show how you ramped up: you scoped what you did not know, read existing code, built a small spike, and identified who knew the area and asked specific questions instead of vague ones.
- Explain how you made sure it was correct without being the expert: tests, an early review from someone experienced, and checking behaviour against the requirement with the analyst or product owner.
- End with delivery and what you learned, and say what you documented for the next person. A story where others did the hard part, or one with no verification step, is the weak version.
Follow-up
- Who did you ask for help, and what exactly did you ask?
- What mistake did you make while learning, and how did you catch it?
- How did you decide when to escalate instead of continuing alone?