Skip to content
tezvyn:

Top 30 Easy Backend Dev Interview Questions and Answers for Freshers

30 easy multiple-choice Backend Dev interview questions, the ones an interviewer opens with: definitions, everyday syntax, and the quick checks that you have really used it. They come from 30 bites in the Backend Dev library, the gentlest slice of the 533 Backend Dev interview questions in the library. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.

Backend engineering, APIs, and databases

30 questions. Pick an answer, or open “Show the answer” to read it.

Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.

  1. Question 1 of 30

    When you annotate a FastAPI route parameter with a Pydantic model, what does the framework do with that type hint?

    Show the answer

    Answer: a · It leverages the hint for automatic request validation and OpenAPI schema generation

    FastAPI reads type hints at startup to construct Pydantic models that validate incoming requests and generate OpenAPI schemas automatically. The distractor about runtime enforcement is wrong because Python itself ignores type hints during execution unless an external tool checks them.

    Read the full bite: Explain Python type hints and their importance in FastAPI

  2. Question 2 of 30

    What is the main reason to place a unique constraint on a non-primary column such as email?

    Show the answer

    Answer: c · To enforce business-level uniqueness while keeping a stable primary key for joins

    The card gives email as an alternate key that stops duplicate signups while the auto-incrementing primary key stays the stable join target. The distractor that it serves as the main row identifier conflates a unique constraint with a primary key, a red flag the card explicitly warns against.

    Read the full bite: What is the difference between primary, foreign, and unique keys?

  3. Question 3 of 30

    When evaluating a new cloud infrastructure project, which statement accurately reflects the trade-off between using Rust versus Go?

    Show the answer

    Answer: a · Rust provides deterministic latency and compile-time data-race safety at the cost of a steeper learning curve, whereas Go trades runtime GC overhead for simplicity and faster onboarding.

    B is correct because it accurately pairs Rust's deterministic, zero-cost memory safety and compile-time data-race prevention with its steeper learning curve, while recognizing Go's GC introduces runtime overhead in exchange for simplicity and faster onboarding. C is a tempting distractor because Go does automate memory reclamation, but its GC does not prevent data races—memory safety and concurrency safety are distinct, and Go leaves more thread-safety responsibility to the developer.

    Read the full bite: Compare Go's GC and Rust's ownership across performance, productivity, and safety

  4. Question 4 of 30

    Which statement best describes how Node.js handles I/O for thousands of concurrent connections?

    Show the answer

    Answer: a · Network sockets are watched by the OS, while blocking tasks like DNS and file reads use a small internal thread pool.

    Node.js relies on the OS kernel to monitor network sockets and notify the event loop when data arrives, while delegating blocking operations like DNS and some file system work to a limited internal thread pool. Distractor D is tempting because Node is famous for non-blocking I/O, but it wrongly assumes every I/O operation can run without thread assistance.

    Read the full bite: How does Node.js handle thousands of connections on one thread?

  5. Question 5 of 30

    You write an async def FastAPI endpoint that calls requests.get. What is the main risk?

    Show the answer

    Answer: c · The event loop is blocked, freezing concurrent request handling until the call finishes.

    The correct answer is C because calling a blocking library like requests inside async def stalls the event loop, stopping all other requests. The most tempting distractor is A because beginners often assume FastAPI magically threadpools any blocking code, but only def endpoints are run in a threadpool.

    Read the full bite: What is the difference between def and async def in Python and FastAPI?

  6. Question 6 of 30

    During a bank transfer, if the debit succeeds but the credit fails, which ACID property ensures the money does not vanish?

    Show the answer

    Answer: b · Atomicity, because the entire transaction must complete or roll back entirely

    Atomicity guarantees that a transaction either fully completes or fully rolls back, preventing partial debits without matching credits. Consistency is a tempting distractor because it concerns valid state invariants, not the undo of incomplete operations.

    Read the full bite: Explain ACID properties and why they matter for banking or e-commerce

  7. Question 7 of 30

    You add a new variant to an error type during a large refactor. Why does Rust typically surface every place needing an update more reliably than Go?

    Show the answer

    Answer: d · Rust's exhaustive match makes non-updated handling sites fail to compile

    Adding an enum variant makes existing exhaustive matches incomplete, so Rust's compiler flags each site. Go's error values do not force callers to branch, so it does not flag missed sites; Rust does not auto-rewrite code.

    Read the full bite: Refactoring under Go simplicity versus Rust correctness

  8. Question 8 of 30

    When adding a new column to a table and then filling it with values, how do the two types of SQL commands involved differ?

    Show the answer

    Answer: d · The first command is DDL that modifies the schema and may lock the table, while the second is DML that changes row data inside a transaction

    Adding a column is DDL because it changes the schema and often locks the table, while updating rows is DML that operates row by row within a transaction. Option B is tempting because it labels the command types correctly, but it is wrong because DDL often auto-commits and cannot be rolled back in many engines, and DML—not DDL—runs inside explicit transactions.

    Read the full bite: What is the difference between DDL and DML in SQL?

  9. Question 9 of 30

    If you write let x = 5 in Rust and x := 5 in Go, which statement about mutability is correct?

    Show the answer

    Answer: c · The Rust declaration is immutable, while the Go declaration allows reassignment without extra keywords

    Rust makes bindings immutable by default, so let x = 5 cannot be reassigned without let mut, while Go variables declared with := or var are mutable by default. Option D is a common misconception because both var and := create mutable bindings in Go, and true immutability requires const.

    Read the full bite: How does Go's variable declaration and mutability differ from Rust?

  10. Question 10 of 30

    Why is it a problem to list a library your source code imports at runtime under devDependencies?

    Show the answer

    Answer: d · A production install that skips devDependencies leaves it missing, causing runtime errors

    Production installs omit devDependencies, so a runtime import placed there will be absent and throw module-not-found. Runtime libraries must live under dependencies.

    Read the full bite: dependencies vs devDependencies in package.json

  11. Question 11 of 30

    What does Node do first when it encounters require('fs')?

    Show the answer

    Answer: a · Matches it against built-in core modules, which take precedence

    Bare specifiers are checked against built-in core modules first; fs is compiled into the binary and resolves without touching node_modules. The package search only runs for non-core bare names.

    Read the full bite: Resolving core vs relative module specifiers

  12. Question 12 of 30

    What is the main mechanical difference between Go's for i := 1; i <= 5; i++ and Rust's for i in 1..=5?

    Show the answer

    Answer: a · Go uses a C-style control statement that manually manages the index, while Rust consumes an iterator hiding index management.

    Go's for is a control statement with explicit initialization, condition, and increment, whereas Rust's for consumes an iterator produced by the inclusive range. Option D is a tempting distractor because both loops look similar, but claiming they are semantically identical misses the statement-driven versus iterator-based gap.

    Read the full bite: Write a 1-to-5 loop in Go and Rust

  13. Question 13 of 30

    When an incoming GET request reaches a FastAPI app, how does @app.get("/") enable the correct function to run?

    Show the answer

    Answer: d · It registers the function in the app's route table at import time and generates OpenAPI metadata.

    The decorator actively registers the function for GET / in the app's internal route table when the module is imported and simultaneously populates the OpenAPI schema, enabling the ASGI layer to dispatch matching requests. Calling it pure syntax sugar is a common misconception because it fundamentally alters the application's routing registry and automatic documentation rather than leaving framework behavior unchanged.

    Read the full bite: What is the purpose of @app.get("/") in FastAPI?

  14. Question 14 of 30

    Which approach correctly defines a FastAPI endpoint that captures an integer item_id from a URL like /items/42?

    Show the answer

    Answer: a · Use app.get("/items/{item_id}") and define async def read_item(item_id: int): then use item_id directly inside the function

    FastAPI binds curly-braced path segments to function arguments with matching names and type hints, automatically converting and injecting the value. Option B is tempting because the route syntax is correct, but the mismatched argument name breaks the default binding unless you use a Path alias.

    Read the full bite: How do you define and access a FastAPI path parameter?

  15. Question 15 of 30

    In the normalized design, CustomerName and CustomerAddress are moved out of the Orders table primarily to eliminate which kind of dependency?

    Show the answer

    Answer: b · A transitive dependency through CustomerID

    Customer attributes depend on CustomerID, a non-key column in Orders, so the dependency is transitive and removing it achieves 3NF. A partial dependency would involve only part of a composite primary key, which is a 2NF concern.

    Read the full bite: Normalizing a flat orders table to 3NF

  16. Question 16 of 30

    Why can't a many-to-many relationship between Students and Courses be modeled with just a single foreign key column on one of those tables?

    Show the answer

    Answer: c · A single foreign-key column can hold only one related value per row

    One foreign-key column stores a single reference per row, so it can only express one side relating to many, not both sides being many. A junction table with two foreign keys is required to represent the full set of pairings.

    Read the full bite: Modeling one-to-many versus many-to-many relationships

  17. Question 17 of 30

    Which statement about a Promise's state transitions is correct?

    Show the answer

    Answer: a · Once settled as fulfilled or rejected, the state is permanent and cannot change

    Settling is one-way and final; a Promise transitions from pending to exactly one of fulfilled or rejected and stays there. then callbacks run later as microtasks, not synchronously.

    Read the full bite: The three states of a JavaScript Promise

  18. Question 18 of 30

    Which statement best explains why you must reassign the result of append to the original slice variable in Go?

    Show the answer

    Answer: d · The append function may allocate a new backing array when capacity is exceeded, so the returned slice header must replace the original variable.

    append may allocate an entirely new backing array when capacity is exhausted, so the returned slice header must replace the original variable or data will be lost. The most tempting distractor claims append always modifies in place, which is false and leads to silent bugs when a reallocation occurs.

    Read the full bite: How do you append to a Go slice and why reassign?

  19. Question 19 of 30

    Given enum WebEvent { PageLoad, PageUnload, KeyPress(char) }, which line correctly instantiates the KeyPress variant with 'q'?

    Show the answer

    Answer: d · let press = WebEvent::KeyPress('q');

    Rust namespaces enum variants under the type with double colons, so WebEvent::KeyPress('q') is correct. WebEvent.KeyPress('q') is invalid because Rust does not use dot notation for enum variants, unlike some other languages.

    Read the full bite: Define a WebEvent enum with PageLoad, PageUnload, and KeyPress

  20. Question 20 of 30

    If you retrieve a User pointer from a map[int]*User and modify its Name field, what happens?

    Show the answer

    Answer: a · The change is visible through every reference to that same User struct

    Because the map stores pointer addresses, retrieving an entry yields a copy of the pointer that still refers to the same underlying struct; modifying a field therefore affects all references. Option B is tempting because maps do copy values on retrieval, but copying a pointer does not isolate the struct it points to.

    Read the full bite: Define a User struct and map of IDs to pointers

  21. Question 21 of 30

    Which method correctly enables automatic JSON body validation in a FastAPI route?

    Show the answer

    Answer: a · Subclass BaseModel and declare it as the type of a path operation function parameter

    FastAPI inspects path operation parameter type annotations to automatically parse and validate incoming JSON against a Pydantic BaseModel. Manually calling request.json() bypasses this automatic pipeline, and response_model only defines the outgoing response schema rather than request validation.

    Read the full bite: How do you define a Pydantic model for FastAPI request body validation?

  22. Question 22 of 30

    Which ACID property guarantees that a committed transaction's effects will survive a server crash that happens immediately after commit?

    Show the answer

    Answer: c · Durability

    Durability ensures committed changes persist to non-volatile storage and survive crashes. Atomicity governs all-or-nothing application before commit, not survival of already-committed data after a crash.

    Read the full bite: The ACID properties of transactions

  23. Question 23 of 30

    When a FastAPI endpoint receives JSON with extra fields not defined in the Pydantic model, what occurs by default?

    Show the answer

    Answer: d · Pydantic silently drops the extra fields and the request succeeds

    By default Pydantic ignores extra fields, silently dropping them so the model instantiates and the request succeeds. Option C is wrong because that strict 422 behavior only happens when you explicitly configure extra to forbid in model_config.

    Read the full bite: How does Pydantic handle extra JSON fields, and how to configure it?

  24. Question 24 of 30

    Two requests each read a counter at 10, add one in application code, and write back. The final value is 11. What prevents this lost update most directly?

    Show the answer

    Answer: b · Performing the increment as a single atomic UPDATE that reads and writes under one lock

    An atomic UPDATE counter = counter + 1 reads and writes the row under one lock, so concurrent increments serialize correctly. Merely raising the isolation level does not fix a read-modify-write performed in application code unless it also locks the row.

    Read the full bite: The lost update anomaly explained

  25. Question 25 of 30

    Two transactions each hold a lock the other needs, forming a cycle. What does a typical database do to recover?

    Show the answer

    Answer: c · Detect the cycle, abort a chosen victim, and let the application retry

    Engines detect the wait-for cycle and roll back one victim to release its locks, then the application retries that transaction. Waiting indefinitely or merging transactions is not how deadlock resolution works.

    Read the full bite: Database deadlocks and how engines resolve them

  26. Question 26 of 30

    What is the key difference between a Pydantic field defined as name: str = 'guest' and one defined as name: Optional[str] = None?

    Show the answer

    Answer: d · The first rejects None while the second accepts it, but both may be omitted from input.

    Both fields have defaults so neither is required, yet str = 'guest' rejects None while Optional[str] = None accepts it. Distractor A is tempting because Optional sounds optional, but requiredness is determined solely by the presence or absence of a default.

    Read the full bite: What is the difference between a Pydantic default and Optional field?

  27. Question 27 of 30

    Why is calling fs.readFileSync inside an Express request handler a problem under concurrent load?

    Show the answer

    Answer: c · It blocks the single event loop thread, stalling all other pending requests

    The sync read blocks the one event loop thread until it finishes, so every other request waits. It is not forbidden and does not spawn threads; the async version uses the libuv pool instead.

    Read the full bite: fs.readFileSync vs fs.readFile

  28. Question 28 of 30

    How do Go and Rust respectively determine whether a function or type is accessible outside its immediate scope?

    Show the answer

    Answer: c · Go exports identifiers that start with an uppercase letter across packages, while Rust uses the pub keyword to make items visible outside their module.

    Go exports uppercase identifiers across packages, while Rust requires explicit pub for module-level visibility. Distractor B is tempting because it correctly names capitalization and pub but wrongly limits Go to file-level scope and Rust to unrestricted crate-wide visibility.

    Read the full bite: How do Go and Rust control visibility of functions and types?

  29. Question 29 of 30

    What does path.join provide that naive string concatenation of path segments does not?

    Show the answer

    Answer: c · Platform-correct separators plus normalization of redundant slashes and segments

    path.join inserts the right separator per OS and normalizes the path. It does not encrypt, speed up reads, or by itself stop traversal attacks, which still require explicit validation.

    Read the full bite: Why use path.join over string concatenation

  30. Question 30 of 30

    In module example.com/shop, directory helpers/ contains files with package utils. What is the correct way to import and use ProcessOrder?

    Show the answer

    Answer: b · Import example.com/shop/helpers and call utils.ProcessOrder

    The import path is always the module path plus the subdirectory (helpers), while the package clause (utils) sets the qualifier used in code. Option A is wrong because it assumes the directory name becomes the code qualifier, a common beginner misconception.

    Read the full bite: Go package declaration, directory name, and import path relationship

Could you explain these out loud?

That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon