This all turned out to be because of the way I’ve set SQLAlchemy up in Pyramid. Essentially you need to follow this section to the letter and make sure you use the same declarative_base instance as the base class for each model.
I was also not binding a database engine to my DBSession which doesn’t bother you until you try to access table metadata, which happens when you use relationships.