5. What we'd do differently

Revision control
Hard to keep source synchronized between JDK and J++ projects. Solution: don't use J++ :-)
Didn't use rcs/cvs during frantic debugging sessions, hard to track source changes
lookup() should expand "user!" meta-tags?
lookup() could expand the "user!" meta-tag in conferences, returning the final address rather than leaving it up to the programmer to perform the dereferencing manually.
Better collaboration between teams
We tended to meet with each of the other teams individually, addressing their needs separately. We may have had better solutions if we all met to discuss component integration between teams, rather than patching on extra functionality on where needed.
STL
Server-side C++ classes could be much cleaner if we used STL Vector and string types rather than simple C-style arrays and strings.
Persistent connections or UDP transport
We chose to use TCP with a single transaction per socket for reasons of simplicity. Persistent TCP connections or a reliable UDP protocol would make communication more efficient. It would also add convenience to users which require frequent lookups (gateway and billing).
Multithreaded server
Having a multithreaded server would allow multiple simultaneous transactions and faster response times, at the expense of more complex database locking techniques.
Use epoch instead of yyyymmddhhmmss
Would make time manipulations simpler.
Security enhancements
All directory service transactions are currently in plaintext. Would be good to drop in SSL instead of vanilla TCP.