One AppBundle. That is the line in the official Symfony Best Practices book I read twice. For years the answer to “how many bundles” was “as many as you have features”, and here the framework’s own book says: one.
The book came out this autumn. Worth reading even if you are not on Symfony, because the interesting part is the change of tone.
The old Symfony way: everything is a bundle. Your application is bundles, reusable, configurable, with their own extensions and semantic configuration. Very flexible. And for a normal business application, mostly ceremony. You write a configuration class for code that will never leave this one project. I wrote such classes. Three of them. None was ever reused.
The book quietly admits it. One AppBundle. Controllers may extend the base controller. Annotations for routing are fine. Constructor injection, thin controllers, sensible defaults. The application is allowed to be just an application.
I like this direction. But the book mixes two things I want to keep apart.
Framework conventions: where files live, how routes are declared, how config is organized. Here just follow the defaults. Every debate about folder structure is an hour of life you do not get back. Defaults end debates. That is their main value.
Architecture principles: thin controllers, explicit dependencies, business logic in services. These are not Symfony conventions. They are portable. They were true in Kohana and they will be true in whatever we all use in 2020.
So: conventions as law, principles as principles, and do not confuse the two. When you deviate from a default, you should be able to say why. If the answer is “this project really needs it”, fine. If the answer is “I prefer it”, follow the default.
I preferred three bundles. The default was right.