We have had a huge ammount of AI in one game I worked on this year where we needed to simulate a 40*40km highway updating a huge ammount of vehicles. Updating a million AI agents per frame is not to solve without a huge server farm I think but why do you want to do this?
Lets assume you have a world where each player is able to see all zombies all the time, even then a zombie will typically not do anything every frame rather than stay arround most of the time. Zombies as every other AI needs a reaction time to seem realistic that may be a few hundrets of milliseconds so dosent even need to update every frame too. Lets assume this, then you could separate those million AI agents so that each agent has its reaction latency and update only a few of them every frame. Assuming 60 frames you have a frametime of 16.667 milliseconds per frame assuming a standard zombie reaction time of 200 milliseconds you need to update N / 11 zombies each frame. This are round about 91.000 zombies per frame.
Now I do not know anything about your gameplay but I do not think that you need to update 91.000 zombies each frame. Assuming a standard zombie size of 60*60cm would mean that you have a reagion of 2.730.000^2 cm or 27,3^2 km without any level geometry between them, a pure wall block of zombies. Even when your player has a view distance of 14 km, you wont need to simulate more than 10% of the zombies per frame in this region because any other zombie is too far away to be seen.
If I would make a game with such many AI, I would cheat wherever possible. Separate those zombies into different update loops that run every 10th frame for any AI that is visible (or faster like I did every 3rd frame for the vehicle AI depending on the driving speed), run your update every 20th frame for each AI that is near the player but not visible and also every 100th frame for the rest. I would do this as a sub task so every update has enought time to run and collect updates for your tasks like a packet of 20 or 50 agents data to continiously send over the network.
As I do not think you need to rotate in all three directions, you could pass one rotation value as 3 bit, one ID value as 20 bit and 35 bit for X/Z axis (Y axis is much less, maybe 16 bit) would mean 14 byte (112 bit) per agent. A 512 byte package can then send updates for 35 agents including some overhead bytes.
Then you should reduce this too by only send updates for agents that have changed there state. I think in a real game this would reduce network traffic to a few kilobytes per second