It appears we have quite a few experinced people on the forum, so please, join in 
I'll start with:
* Don't do IO in main loop, copy (relevant) game state and spawn another thread to do serialization of the copy.
It'll complicate code, but I think it would be worth it. Just pay close attention to thread synchronization and IO failure handling.
* Use SQLite instead of your in-house file format for both Ironman and non-Ironman. (original suggestion by @penco)
That would
a) reduce code base
b) make life of 3rd party tools builders easier
c) You can always and easily expand it. Adding new tables and maybe relations is safe and doesn't cost you anything.
I'll start with:
* Don't do IO in main loop, copy (relevant) game state and spawn another thread to do serialization of the copy.
It'll complicate code, but I think it would be worth it. Just pay close attention to thread synchronization and IO failure handling.
* Use SQLite instead of your in-house file format for both Ironman and non-Ironman. (original suggestion by @penco)
That would
a) reduce code base
b) make life of 3rd party tools builders easier
c) You can always and easily expand it. Adding new tables and maybe relations is safe and doesn't cost you anything.