I want to give the (correct) answer by Maxim Kim a bit more context.
The root of the misunderstanding lies in how the :substitute command interprets its arguments. In :help :substitute, we see (omission mine):
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count] [ two lines omitted for clarity ] For the {pattern} see pattern. {string} can be a literal string, or something special; see sub-replace-special.
We see that we have two arguments, separated by / (or whatever separator you choose) and their types are pattern and string, respectively. In a strongly typed language, we would have a signature like substitute(RegEx, String) which would make the difference obvious.
Now that we've established that pattern and string are different types, we have no inclination to believe they would behave the same. To the contrary, the fact that so many escape sequences do behave the same tends to confuse users.
Or, to answer the original question:
Why is that?
Because pattern != string.
When we follow the hotlinks in :help :substitute to :help pattern and :help sub-replace-special, we eventually arrive at the sections quoted in Maxim's answer.
Below :help pattern.txt, we find :help /\n:
\n matches an end-of-line
And below :help change.txt, we find:
<CR> split line in two at this point (Type the <CR> as CTRL-V <Enter>) \r idem \<CR> insert a carriage-return (CTRL-M) (Type the <CR> as CTRL-V <Enter>) \n insert a <NL> (<NUL> in the file) (does NOT break the line)
If nothing else, we learn that we could also use <C-V><CR> (shows up as ^M) in the replacement string. I'd stick with \r, YMMV.