The manual contains more information in the record section:
A record type is resolved through finding that single explicit type declaration (we call this “nominal typing”), the type error messages end up better than the counterpart (“structural typing”, like for tuples). This makes refactoring easier; changing a record type’s fields naturally allows the compiler to know that it’s still the same record, just misused in some places. Otherwise, under structural typing, it might get hard to tell whether the definition site or the usage site is wrong.
There is one exception to this rule and that is inside a variant declaration:
type user =
| Number(int)
| Id({name: string, password: string})
Both are zero-runtime, so either is fine depending on your situation. It’s possible that you end up changing them from objects to to records afterward anyway, or the other way around. Doesn’t matter!