I assure you it works well with 25000 people, I've worked in such an environment.
It seems to me that in the various threads I read here that there seems to be a bit of misunderstanding. If you work on short lived feature branches and merge them to trunk/master and other people branch new feature branches from trunk/master and so on you might be just doing TBD without calling it that way.
Many things are just common sense consequences of that, e.g.
if other people are spawning their feature branches from trunk/master; then you don't want to merge something that breaks trunk/master, otherwise you'd be making the life for your colleagues harder, since now they cannot know whether the code they added breaks some tests or they are broken because somebody else broke them.
The feature-flag thing comes into play only when you want to break down a larger feature into smaller branches, each landing in trunk/master before continuing the next step. This get more important the more people can actually make changes on the same part of the codebase that you big feature is going to touch.
If it's only you that touches a section of your code base (and you can do it because it's well modularized), you won't feel much pain of making your feature branch last longer.
However, TBD shows its strengths precisely when the team grows; when you no longer can make the assumption that only you will work on a given piece of code.
> you might be just doing TBD without calling it that way
I think this happens an astounding amount. In particular, i think Git Flow is TBD with the names swizzled.
As far as i know, all the source control disciplines that people seriously advocate involve:
1. Developers working on local copies of the code
2. A shared copy of the code where developers integrate their work when they're done
3. A copy of the code used to make releases, which is refreshed or recreated from the shared copy
These copies get different names, which are meaningless labels. In TBD, the shared copy is called 'trunk', and the release copy a 'release branch'. In Flow, the shared copy is 'develop' and the release copy is 'master'. They're just names. They don't matter.
The precise mechanism for moving work from local copies to the shared copy varies, but not in a way which really matters. In TBD, developers usually push straight to the trunk. If they're doing XP, they've done code review via pairing. In some teams, there might be pre-merge code review through a tool like Gerrit, Reviewboard, Phabricator, or some such, but still with an expectation of a merge happening quickly. In Flow, i guess there are pull reviews, but those are basically the same, a code review before merging. The Not Rocket Science Rule is this, but enforced by a robot [1].
The mechanism for moving work from the shared copy to the release copy varies a bit more. Strict CD shops release the trunk, but they will only push the latest point on the trunk which has passed all the checks, which is a bit like having an implicit branch. Conventional TBD cuts release branches. Flow does, that, and then adds a bit of a dance around merging individual release branches into the long-lived master branch, but it doesn't ultimately matter, because any changes made on an earlier release branch have already been merged back into develop. There's variation in where you fix urgent bugs: on the shared copy, followed by a copy to the release copy, or on the release copy, followed by a copy to the shared copy. I'm not sure that this is very significant.
Which leaves the only significant tuneables being how often developers integrate their changes, and how often the team makes releases. If you integrate often, you get easy merges and rapid integration feedback. If you integrate infrequently, you don't get those things. If you integrate more frequently than you release, then you will need disciplined incremental development, feature toggles, or some other way of making incomplete features unavailable in production.