Interview Handbook by Sayed Elmahdy العربية

Topic 34 · Bonus: optional but valuable

Advanced topics (bonus)

Event sourcing, GraphQL, Blazor, the actor model and Orleans, Dapr, feature flags, WebAssembly, gRPC streaming.

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

15 questionsMid · 8Senior · 710 quiz

Concepts

What you will learn: Explore advanced choices when a real need appears: preserving order history, shaping responses, interactive , coordinating distributed work or routing traffic. Each card starts with the problem and explains when a technology helps and what it costs to operate.

Before you start: Familiarity with APIs, , dependency injection and running a service helps. An event records something that happened; a receives and routes requests; an actor or grain is an entity that processes messages and manages its state. Cards are optional and independent, so begin with the problem closest to your work.

Select a term with a dotted underline for its meaning, then continue reading from the same place.

#Event sourcing: events as the source of truthBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

A worked example
  1. Rather than storing only balance 70, retain events such as Deposit 100 and Withdraw 30. Applying them in order derives balance 70.
  2. Events are the source of truth in ; a balance screen may use a derived . Adding diagnostic events beside an authoritative state table does not make the design event-sourced.
  3. Rebuilding state must not automatically repeat external charges or old emails. Separate state derivation from external effects and plan event evolution and replay cost before adopting the design.

When you need every meaningful transition and its reasons rather than only current state, event sourcing stores a sequence of events instead of replacing a state record. State is rebuilt by replay, while projections serve reads. This differs from adding an audit log beside an authoritative current-state table.

This C# sketch demonstrates replay only, not an event store; durable append needs an atomic expected-stream-version check.

public abstract record OrderEvent;
public sealed record OrderPlaced(decimal Total) : OrderEvent;
public sealed record OrderCancelled : OrderEvent;

public sealed class OrderState
{
    public decimal Total { get; private set; }
    public bool Cancelled { get; private set; }

    public void Apply(OrderEvent e) // (1)
    {
        switch (e)
        {
            case OrderPlaced placed: Total = placed.Total; break;
            case OrderCancelled: Cancelled = true; break;
        }
    }
}

var state = new OrderState();
foreach (var e in history) state.Apply(e); // (2): history is ordered OrderEvent data
🧾 Code walkthrough
  1. (1) Apply only rebuilds state; it must not email or charge during replay. Validate commands before creating events, rather than rejecting historical facts under today's rules.
  2. (2) Per-stream order matters. Versioned snapshots accelerate replay but remain derived data.

Costs include evolution and upcasters, projection lag and rebuilds, and personal-data removal from long-lived history. Avoid it for ordinary without a real historical-state requirement. Event sourcing and do not require each other.

Event sourcing trade-offs

#GraphQL in .NET versus RESTBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

When mobile and web clients need different response shapes, GraphQL lets clients select fields from a typed . Hot Chocolate implements a GraphQL server in . remains useful for straightforward contracts, caching and explicit business commands; neither approach is universally superior.

# GraphQL operation against an illustrative store schema
query {
  order(id: "123") {
    id
    lines { quantity product { name } }
  }
}

Resolvers can each issue a query, causing . DataLoader batches key-based reads within a request, while limits columns. Require pagination and depth/cost limits, and authorize resources and fields. Fewer HTTP requests do not imply less database work. Never share a DataLoader cache across tenant boundaries. The operation is an illustrative contract, not a complete C# server.

RESTGraphQL
ShapeServer defines each endpoint responseClient selects from a schema
CacheUsually direct HTTP semanticsNeeds deliberate operation and response policy
CostPossible over-fetchingQuery-cost and resolver complexity

Hot Chocolate batching

#Blazor render modes for backend developersBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

A Blazor Web App chooses where components execute interactively. This affects operations, security and , beyond page appearance.

ModeExecutionTrade-off
Static SSRServer-generated without Blazor interactivityLightweight; interaction needs another mechanism
Interactive ServerServer components with SignalR updatesSmaller initial payload; connection, circuit memory and network latency
Interactive in the browserRuntime and app download; backend must distrust the client
Interactive AutoServer initially, WebAssembly on later visits once the bundle is availableCode and services must work in both environments

Auto does not migrate a running component from server to browser mid-session. Interactive modes support prerendering by default; loading may occur in two phases, requiring state handling and prevention of duplicate side effects. Keep secrets and authorization on the server regardless of mode.

Render mode reference

@* In a .razor component after enabling the mode in the Blazor host. *@
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@rendermode InteractiveServer
<button @onclick="Increment">Items: @count</button>
@code {
    private int count;
    private void Increment() => count++;
}

#The actor model and Microsoft OrleansBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

For per-entity state and behavior, such as bookings or carts, actors receive messages instead of exposing shared memory to arbitrary threads. Orleans provides virtual actors called grains, with stable identity, runtime-managed activation and distribution across silos.

Client -> Grain reference (BookingId) -> active grain on a silo
                                         |
                                  explicit persistent state
Silo failure -> later activation elsewhere -> reload persisted state

Default scheduling serializes requests for ordinary grains; reentrancy and interleaving settings change the reasoning. This is neither an automatic across grains nor automatic persistence of every field. Design persistence, and timeouts explicitly. One heavily accessed entity can become a hot grain; more servers do not inherently split one key's workload. Simple may be easier without an additional cluster.

Orleans overview

#Dapr building blocksBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

Dapr exposes common for invocation, pub/sub and state across services and languages, backed by components for different providers. A common deployment uses an or sidecar. The and state store still exist and require configuration.

Building blockUse
Service invocationCall an app ID through service discovery
Pub/subPublish and consume events through a component
StateKey-value state with store-dependent capabilities
Secrets and bindingsRetrieve secrets and connect external systems
Actors and workflowsCoordinate state and long-running processes

An abstraction does not guarantee identical or consistency across stores. Test component metadata, retries, dead-letter behavior and permissions. Sidecar and operational costs may outweigh benefits for one simple API. Aspire handles local orchestration and service defaults; it does not automatically replace Dapr's runtime.

Dapr building blocks

#Feature flags: separating deployment from releaseBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

let you deploy code separately from enabling it, supporting gradual rollout. Microsoft.FeatureManagement provides evaluation, filters and variants. A flag is not authorization; permission checks remain necessary.

This service fragment assumes services.AddFeatureManagement(), an injected IVariantFeatureManager named features, and application-defined rendering methods.

using Microsoft.FeatureManagement;

bool useNewCheckout = await features.IsEnabledAsync("NewCheckout"); // (1)
return useNewCheckout
    ? RenderNewCheckout()
    : RenderCurrentCheckout();                                     // (2)
🧾 Code walkthrough
  1. (1) Evaluate once for this decision; use snapshot evaluation where request-level consistency is required. Targeting needs stable, trusted identity.
  2. (2) Test both branches. A kill switch stops future behavior; it does not undo a migration or completed refund.

Give each flag an owner, purpose and removal date. Monitor cohort impact and define safe configuration-failure behavior. More flags create more combinations to test.

Feature management reference

#WebAssembly and WASI brieflyBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

is a portable execution format hosted by a runtime, inside or outside a browser. It can suit plugins, shared code or sandboxed workloads. defines system interfaces available to WebAssembly according to the host and interface version; it is not a complete operating system.

Compiled module -> Wasm runtime -> explicitly granted host capabilities
Browser host: browser APIs and interop rules
WASI host: supported WASI interfaces and configured capabilities
Check .NET toolchain, runtime, interface version and package compatibility.

A sandbox still needs runtime updates and /memory limits. Never put secrets in a client bundle, and do not assume arbitrary NuGet packages or apps run under WASI unchanged. and WASI support evolves; verify the exact toolchain rather than promising universal compatibility.

WASI introduction

#gRPC streaming and connection lifetimeBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

For progress updates or event streams, supports unary, server-streaming, client-streaming and bidirectional calls. Proto contracts generate C# types. This finite server-streaming example is not a durable event subscription.

syntax = "proto3";
option csharp_namespace = "Store.Contracts";
service Progress { rpc Watch (WatchRequest) returns (stream ProgressReply); }
message WatchRequest { string order_id = 1; }
message ProgressReply { int32 percent = 1; }
// In a Grpc.AspNetCore project with C# generated from the proto above.
using Grpc.Core;
using Store.Contracts;

public sealed class ProgressService : Progress.ProgressBase
{
    public override async Task Watch(WatchRequest request,
        IServerStreamWriter<ProgressReply> stream, ServerCallContext context)
    {
        for (int n = 0; n <= 100; n += 25)
        {
            context.CancellationToken.ThrowIfCancellationRequested(); // (1)
            await stream.WriteAsync(new ProgressReply { Percent = n }); // (2)
            await Task.Delay(100, context.CancellationToken);
        }
    }
}
🧾 Code walkthrough
  1. (1) Cancellation and deadlines bound execution. Authorize order ownership before a real stream; this example emits constants only.
  2. (2) Await each write and use one writer. Do not accumulate unbounded messages when clients are slow.

Check proxy timeouts and /2 support. Browsers need gRPC-Web or another approach; gRPC-Web does not provide native client or bidirectional streaming. If event loss is unacceptable, reconnect requires a resume cursor and deduplication; opening a new connection alone does not replay data.

gRPC service contracts

#YARP as a reverse proxyBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

To route some requests to a new service and keep others on a legacy system, provides a reverse-proxy library hosted in . Routes match requests; clusters define destinations and load-balancing behavior. It suits incremental migration or a customized gateway, with operations remaining your responsibility.

This uses Yarp.ReverseProxy and a validated ReverseProxy configuration section containing routes and clusters; the fragment does not define destinations by itself.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")); // (1)
var app = builder.Build();
app.MapReverseProxy();                                               // (2)
app.Run();
🧾 Code walkthrough
  1. (1) Loads routing configuration. Never let arbitrary clients choose destination URLs, creating an open proxy or path.
  2. (2) Maps proxy endpoints. Add authentication and authorization according to the design, while destinations still enforce permissions.

Review trusted forwarded headers, , , timeouts, request sizes and propagation. A is not automatically a full service mesh or WAF. A managed gateway may meet the need with less operational work.

YARP setup

#Hangfire, Quartz and TemporalBonus

Optional but valuable: not asked in every interview, but knowing it deepens your understanding and sets you apart.

Task.Run inside a request is not a job system: the process may stop and the request scope may disappear. Choose based on whether you need persisted jobs, rich scheduling or long-running workflows that recover progress.

ToolFitsYou manage
HangfirePersisted background jobs, retries and a dashboardStorage, workers, and dashboard access; some commercial features are separate
Quartz.NETJobs, triggers, calendars and misfire policiesPersistent stores and clustering as needed; business workflows remain application logic
TemporalDurable workflows with waiting, coordination and recoveryService, workers, history and versioning; deterministic workflow code

Temporal activities contain and side effects. Workflows replay from history, so use primitives instead of ordinary clocks, randomness or calls. Activities can repeat and need idempotency. For every tool, monitor oldest-job age, failures and retries; use an when enqueue intent must be atomic with business writes.

Hangfire · Quartz.NET · Temporal .NET

Interview questions

Check your reasoning

Why does this choice fit? When would it fail? What changes under higher load or a dependency failure?

34.1When would you choose event sourcing?Senior
Model answer

I consider when the history of business transitions is central, and rebuilding or deriving state from that history provides concrete value. I store events as the authoritative record and build read projections, with expected-version checks for concurrent writes. I also budget for event evolution, replay testing, lag and personal-data handling. For ordinary with modest audit requirements, a current-state model and an audit trail may be simpler. alone does not require event sourcing.

34.2How do you replay events safely?Senior
Model answer

I keep event application deterministic and free of external side effects, so replay cannot resend emails or charge customers. Commands are validated before new events are appended; historical facts are not revalidated against today's business rules. I version event contracts and use tested compatibility transformations where needed. Snapshots accelerate reconstruction but remain disposable derived state. I test rebuilding projections from history and define how live traffic is handled while a new catches up before switching reads.

34.3When would GraphQL be useful compared with REST?Mid
Model answer

I consider GraphQL when several clients need different shapes of related data and a typed can reduce endpoint proliferation. can be simpler for stable resource contracts and conventional caching. With GraphQL I still need pagination, resource authorization, query-cost limits and efficient resolvers. One request can create substantial backend work, so I do not equate fewer round trips with better database performance. I choose based on client needs and operational complexity rather than treating either style as universally better.

34.4How do you avoid N+1 in Hot Chocolate?Mid
Model answer

I look at resolver access patterns and actual database command counts. For related objects requested by key, a DataLoader can batch reads and cache them within the request. I also use suitable projections and pagination rather than loading an entire graph. The loader must respect tenant and authorization context, and its cache should not leak across requests. I test with multiple parent records, because a single-record test can hide behavior even when every individual query is fast.

34.5How do Blazor Server, WebAssembly and Auto differ?Mid
Model answer

I distinguish where interactive component code executes. Interactive Server keeps it on the server and sends updates over SignalR, trading a smaller initial download for connection and circuit costs. Interactive runs in the browser after downloading the runtime and application. Auto can start with Server and use WebAssembly on subsequent visits once the bundle is available; it does not migrate an active component mid-session. In all modes, sensitive operations and authorization remain enforced by server-side services.

34.6What can go wrong with Blazor prerendering?Mid
Model answer

I check whether initialization and data loading occur during prerendering and again when interactivity starts. If that path performs a side effect, it can happen twice. I keep initialization safe, preserve state where appropriate and avoid assuming browser or client-only services exist during server rendering. Disabling prerendering can be an intentional choice, but it changes the loading experience. I test both the initial render and interactive phase rather than validating only an already-running component.

34.7What does Orleans simplify, and what does it not solve?Senior
Model answer

I use Orleans to simplify entity-oriented distributed behavior through virtual grains with stable identity and runtime-managed activation. It reduces manual placement and coordination code, and ordinary grain scheduling helps reason about local state. It does not automatically persist every field, guarantee exactly-once effects or make several grains one . I still design persistence, timeouts, retries and cross-grain consistency. A hot grain can remain a bottleneck, so I examine key distribution and workload shape before choosing the model.

34.8What value does Dapr add to a .NET service?Mid
Model answer

I see Dapr as a set of building-block backed by configurable infrastructure components. A service can use invocation, pub/sub, state and other capabilities through a common interface, which can help a polyglot system. I still need to understand the selected and state store because capabilities and guarantees differ. The runtime also adds configuration, security and operational work. For a simple service with established libraries, that extra layer may not provide enough benefit.

34.9How do you use feature flags safely?Mid
Model answer

I use to separate deployment from exposure, with a defined owner, rollout plan and removal date. I test both enabled and disabled paths, use stable targeting and monitor cohort outcomes. Authorization remains independent of the flag. I also define behavior when configuration is unavailable and keep evaluation consistent within an operation. A kill switch can stop future behavior, but it does not reverse data migrations or completed side effects, so rollout and rollback plans must account for those separately.

34.10What is the relationship between WebAssembly and WASI?Mid
Model answer

I describe as a portable execution format and as standardized system interfaces that a host may provide to modules. WebAssembly can run in browsers or other runtimes, but those environments expose different capabilities. I verify the exact runtime, interface version and toolchain rather than assuming arbitrary packages work unchanged. Sandboxing helps constrain access, but resource limits, host permissions and runtime updates are still necessary. Client-side execution also cannot protect embedded secrets.

34.11What changes when a unary gRPC API becomes a stream?Senior
Model answer

I now need to manage a longer-lived operation: cancellation, deadlines, slow readers, bounded buffering and proxy timeouts all matter. I keep stream writes serialized and await them instead of queuing unlimited work. I define what happens after disconnection, including whether clients can resume from a cursor and how duplicates are handled. A stream itself is not durable delivery. I also check browser compatibility because -Web does not offer every native gRPC streaming pattern.

34.12What security issues matter in a YARP reverse proxy?Senior
Model answer

I restrict destinations to trusted configuration so the proxy cannot become an arbitrary forwarding or service. I define authentication and authorization policies, preserve only intended identity information and configure forwarded headers from known proxies. I also review validation, request limits, timeouts and access logging. Backend services still enforce resource permissions. Operationally, I test , routing changes and propagation, because a proxy is a critical shared component rather than merely a convenient routing function.

34.13How would you choose between Hangfire, Quartz and Temporal?Senior
Model answer

I start with the execution model. Hangfire is a practical fit for persisted application jobs with retries and operational visibility. Quartz is attractive when scheduling, calendars and trigger behavior are central. Temporal suits durable workflows with waiting, coordination and recovery across steps, but adds a service and replay constraints. These tools overlap, so I compare the actual requirements and operational cost. In every case, I design effects and address atomicity between business writes and job publication.

34.14Why must Temporal workflow code be deterministic?Senior
Model answer

Temporal reconstructs workflow progress by replaying recorded history, so workflow code must make compatible orchestration decisions during replay. I keep external and side effects in activities and use workflow-provided primitives for time and waiting. Activities can execute again, so they need where duplication matters. I also plan code evolution for workflows already running, using the platform's versioning guidance. Ordinary clock access or arbitrary network calls inside workflow code can make recovery diverge from the recorded execution.

34.15Why is Task.Run not a reliable background job queue?Mid
Model answer

Task.Run schedules work in the current process; it does not persist intent or guarantee execution after a restart. Work launched from a request can also outlive its scoped dependencies, and its failures may be unobserved. For suitable in-process work I can use a bounded queue and BackgroundService with explicit scopes, accepting its durability limits. If the work must survive process failure, I choose persistent job infrastructure and coordinate publication with business writes, often through an .

Test yourself

Quiz answers and completed-topic marks are saved in this browser; they do not sync across devices.

Score: 0 / 0

What is authoritative in event sourcing?

Projections and snapshots are derived from events.

What must replay avoid?

Replay must not resend emails or repeat charges.

Which technique batches GraphQL key-based reads?

DataLoader addresses with proper scoping and permissions.

How does Blazor Auto normally use WebAssembly?

Auto is not live migration of an active component.

What does an Orleans grain not automatically provide?

Persistence and cross-grain consistency need explicit design.

What must remain independent of a feature flag?

A flag controls exposure, not resource permission.

What is WASI?

Support depends on runtime, interfaces and toolchain.

A slow gRPC client cannot consume messages quickly. What should the server do?

This is part of and operation lifetime management.

Which is a safe YARP destination policy?

Arbitrary destinations can create or an open proxy.

Where should external I/O normally live in a Temporal application?

Workflow orchestration is deterministic; activities perform external effects.