The docs for @spawn mention using $ to interpolate variable values into the generated closure. If you look at the code, the macro gathers up all variables preceded by $ into a let block around the task body. (The @async macro uses the same helper function).
In general, though, I would absolutely avoid reusing the variable like you have there. You can just put the @spawn inside the fetch() call if you want:
let x = 1
fetch(@spawn $x + 3)
end