The id member is a switch. A Request object with no id is a notification: the server runs the handler and MUST NOT send a response object — not a result, not even an error.
That is the contract, not an optimisation. A client that sent a notification is not reading for a reply, and writing one desynchronises a pipelined connection: every subsequent response is matched against the wrong request.
The spec is careful about one distinction people flatten:
| body | meaning |
| --- | --- |
| {"jsonrpc":"2.0","method":"log"} | notification — no reply |
| {"jsonrpc":"2.0","method":"log","id":null} | a call whose id happens to be null — reply with "id":null |
An absent id and an explicit null id are different requests.
