Interview question
Map a unique email race to a conflict response
Relies on a database unique constraint and translates only the expected provider error into a domain conflict.
TL;DR
Relies on a database unique constraint and translates only the expected provider error into a domain conflict.
Database uniqueness, race conditions, DbUpdateException classification, conflict responses, and avoiding broad exception swallowing.
Practice the problem like a real interview: restate, reason, implement, and test.
Users.NormalizedEmail has a named unique index. A preliminary existence check may improve the common response but cannot guarantee correctness. Save the new user and map only that named unique-constraint violation to EmailAlreadyExists through a provider-aware error classifier.
Move to the linked follow-up, next path step, prerequisite, or deeper variant.
Practice the next layer of the same subject.
Two requests pass an optional existence check at the same time. One insert succeeds. The other receives the database uniqueness error and returns a conflict rather than creating a duplicate or a generic server error.
I attempt the insert and catch DbUpdateException only when a provider-aware classifier identifies the expected unique index. This keeps the endpoint portable at the application boundary while the infrastructure classifier understands SQL state or provider error codes. An existence check alone is never enough because it leaves a race window.
public static async Task<CreateUserResult> CreateUserAsync(
AppDbContext db,
IDatabaseErrorClassifier databaseErrors,
CreateUser request,
CancellationToken cancellationToken)
{
var normalizedEmail = EmailNormalizer.Normalize(request.Email);
var user = User.Create(request.Email.Trim(), normalizedEmail);
db.Users.Add(user);
try
{
await db.SaveChangesAsync(cancellationToken);
return CreateUserResult.Created(user.Id);
}
catch (DbUpdateException exception)
when (databaseErrors.IsUniqueConstraint(
exception,
"ux_users_normalized_email"))
{
return CreateUserResult.EmailAlreadyExists();
}
}
The successful path is one insert. Under contention, the unique index serializes the business key and one writer fails predictably. The provider-specific classifier should have focused integration tests against an isolated test database or container because in-memory providers do not reproduce relational constraint errors.
Spot a weak answer, missing edge case, or clearer explanation? Send it in.