I think I would have to see you draw a sequence diagram to make sure, but I think we are seeing the same race condition -- the end result is a record isn't included because it saw a task was already created but the builds had already pulled the database for a zone's content.

As for other ways of fixing this, I'm sure some exist. Here are the reasons behind why things work the way it was: Tasks are created after any record is changed. The idea is that when the build starts it declares "I see these Y tasks and will rebuild these zones" [0]. After the builds complete, the build script says "I will remove *only* the Y tasks I saw at the beginning of the build" [1]. This ensures that any tasks created during the build are picked up on the next build. I like this solution because it doesn't involve locking and it doesn't involve shared state between the WSGI process creating/updating records and the build script.

[0] https://github.com/OSU-Net/cyder/blob/master/cyder/cydns/cybind/builder.py#L470
[1] https://github.com/OSU-Net/cyder/blob/master/cyder/cydns/cybind/builder.py#L503