Well there are 2 ways.
The first involves the creation of a trigger system.
Each player owns 1 base. Thus give each base an array index of an array of units. There is also a spawn type for each player, a spawn rate, a current spawn rate counter and a spawn number.
Ever second you loop through all players, decrimenting their current spawn rate counter unit it is 0 in which case you spawn spawn number of spawn type units and then reset current spawn rate counter to spawn rate.
Upgrading the main structure changes the values (another trigger system) for the upgrading player. Technologies might also change the values.
The alternative is to use the data editor. You could use a perodic behaviour with the spawn effect to spawn units with a validator for a cap. You could use a spawn behaviour with maximum number of spawn positions in it. You could even use a perodic behaviour to order the main building to build the spawns.
The data editor method allows better intigration with data elements. The trigger method allows better customization and flexibility.