This question tests whether you understand that COMMIT is a physics problem, not an API call. The database cannot tell the client "committed" until the transaction's effects are crash-proof — which means they are on disk. Everything interesting about commit is about making that disk write cheap.
The mental model: writes never touch disk directly. BEGIN allocates a transaction ID and a snapshot — no I/O. Your INSERTs and UPDATEs mutate pages in the buffer pool, a shared in-memory cache. Those pages are now dirty; if the server crashed right now, the changes would vanish. That's acceptable — the transaction isn't committed yet.
The trick is the write-ahead log. Every change also appends a small sequential record to the WAL: the page, the offset, the old and new bytes, tagged with the transaction ID and a monotonically increasing log sequence number (LSN). Log appends are sequential writes to one file, so they're fast — microseconds to append, versus flushing random 8KB pages all over the data files.
COMMIT does exactly one expensive thing: it flushes the WAL up to the transaction's commit record with an fsync — the OS is forced to push the log buffer through the disk controller's cache to stable media. Only after that fsync returns does the commit status get recorded in the commit log and the client get its response. That ordering is the durability guarantee: the WAL record hit the disk before anyone was told "committed," so recovery can replay it even if the whole machine dies.
Two mechanisms make this survivable at scale. First, group commit: many concurrent transactions arriving within milliseconds of each other share one fsync — the log is flushed once, covering all of them, and each commit then costs a few microseconds instead of a 1-10ms disk rotation. Second, checkpoints: data pages are flushed to the data files lazily in the background, so commit never pays for them.
The edge cases are where senior answers live. synchronous_commit = off skips the fsync and commits as soon as the log buffer is written to the OS — roughly the last second of transactions can evaporate on power loss. Distributed transactions replace the single commit record with a two-phase commit across participants. And an fsync that succeeds but a network response that's lost means the client retries and the database must idempotently report the same result — that's the full-commit-semantics question hiding behind every "just retry" answer.