Depends on the flexibility you want to allow your customers.
We’ve built our dialplan in sections for each feature they get to use, each instance of a feature is contained in a single context.
Eg. you have an IVR, we make a context like
customerident-ivr-1 for the first, ivr-2 for the second, and so on. Same goes for queues, playback of audio files, like a welcome message etc. Some things are common contexts used for all users, just regulated by channel variables, eg. setting callerID, handling call forwarding etc.
When the customer build their setup, they see a visual representation of the features as blocks connected to each other. When they want to change the connection, they just connect the blocks differently, if they want to eg. change the options of the IVR, they click the block and gets access to the options.
When they are satisfied, they apply their configuration, at which point the flow they built is converted to dialplan with each block being a dialplan template, we fill in the dynamic information eg. the audio for playing the IVR menu, it’s options and destinations, and finally reload the configuration on Asterisk, and the customer is notified that their changes are now live.
We designed our system from the philosophy that the PBX should be independant of outside sources as much as possible, as such we’re not using realtime for extensions or dialplan, just plain old auto generated dialplan.
If I were to do this today, I might consider writing the dialplan in AEL or LUA, to allow for more flexibility and reuse, or use AGI a lot more to cut down on dialplan required, as this way of doing things results in a LOT of similar looking dialplan, in lots of files (Split up to make troubleshooting easier, and keep customers dialplans separated.)
We also have a problem where Asterisk is not always loading all configuration properly, usually this results in PJSIP endpoints or queues missing in the system, currently we have not figured out the reason, we just check the live config against the configuration files after the first reload is done, if something is missing, we do another reload, which usually fixes the problem.
My suspicion is that Asterisk (Or the affected modules) does not like the amount of lines in the combined configuration files, or the number of files loaded. But if you end up with a lot of files, or a lot of lines in your configuration files, beware of this possible problem.