I've left some comments on PS8.
The race condition is a result of the way the data is structured and stored: the entire collection and its metadata is stored in one wiki page as a JSON blob, which can't be updated without reading and writing the complete manifest.
In the example you've provided, you create and manipulate two new collections simultaneously. If the requests are processed at roughly the same time, then both fail to load the user's collections, create a new one and attempt to write a manifest with a single collection in it. Both API requests will succeed but only one collection will exist. Only if there's a significant delay – longer than it takes to process a single request, say – in the processing of one of the requests, or the requests are ordered, then the first request will successfully create a manifest with a single collection in it and then the second request will add a new collection to the manifest.
An alternative implementation, which AFAICT you've already considered, is to use sub-pages to store collections, e.g. User:Phuedx/Collections/Favourite_Post-metal_Albums, where the User:Phuedx/Collections page acts as a manifest but you never explicitly update it. Don't worry about auto-incrementing IDs, just map the name of the collection to the title of the sub-page. A nice consequence of this is that the URLs are human-readable. Better still, the Title class can do all of the heavy lifting (see Title::makeTitleSafe and Title#getSubPages).
Note that you may still see race conditions at the collection level, if, say, the user is editing the collection of their favourite post-metal albums* in multiple windows or tabs or across multiple devices.
–Sam
* Got any suggestions?