A very good question indeed, here is a bit of insight.
CDI EG (expert group) decided against mixing those two for several reasons:
- Backward compatibility
- Existing applications use synchronous and it needs to behave equally
 
- Keeping the same annotation would require you to add extra option to differentiate anyway
 
 
- Return type
- Calling 
Event.fireAsync() gives you a CompletionStage to which you can chain next steps with exceptionally() or thenApply() etc. This naturally fits into asynchronous programming model. 
- Good old 
Event.fire() only gives you void, to which you cannot react at all - not good for async 
- Again, the return value of synchronous one cannot be changed due to backward compatibility  
 
 
- Excepting handling differs a lot
- Exception in synchronous notification == end of chain, you blow up
 
- Exception in asynchronous notification == you keep going and gather all exceptions from observer methods (possibly from multiple threads!) and then present them back to invoking code. Since it's 
CompletionStage, you can easily react to that. 
- Mixing the two would lead to a very confusing result on user side - when would you blow up and when do you keep going? What is the true outcome of 
Event.fire() (if it were for async as well) 
 
- Internal observer processing
- It would be very complex (assuming it would even be possible) to mix sync and async
 
- Bear in mind that you need to strictly draw a line between which is going to be sync and async as contexts do not propagate in other threads (for instance 
RequestScoped needs to be re-activated, by Weld, in the async observer thread) 
- Similar troubles come with security context propagation for integrators
 
- There is often pre-processing of observers to make it work really fast, if you have one observer method for both, you cannot really pre-process it as you never know what it will be used for
 
 
Other advantages of the current model I can think of:
- Presence of 
fireAsync() allows you to fire event with additional options
 
- Last but not least - user experience
- This way it is clear, that what you had before works exactly the same
 
- And that for 
fireAsync() you have matching @ObservesAsync