You can certainly port slow Erlang code to C, but it's not as straightforward as doing so in, say, Python or Ruby. For one, if your C code crashes, it's not the calling Erlang process that crashes, but the entire VM [1]. Second, NIF implementations are supposed to cooperate with the BEAM scheduler and only run for 1ms at a time. jlouis points out that most NIFs fail at this [2]. Third (and maybe the expectation here is too great), binary data (structs, etc.) used/provided by NIFs are "magic binaries" which cannot be pattern matched and are represented in crashes, the REPL, etc. as "<<>>" which can be confusing [3].
> For one, if your C code crashes, it's not the calling Erlang process that crashes, but the entire VM [1].
NIF's are one of several ways of linking C and Erlang, and the one most similar to how Tcl/Python/Ruby/etc... link in C code. In those runtimes, if your C code segfaults, you will also crash the interpreter. You're correct that they're a bit trickier to integrate because you have to consider the scheduler, whereas Tcl/Python/Ruby don't care if you call out into the C code and it takes a minute to complete.
Erlang offers you other means of working with C code, like ports, and C nodes, which can comunicate at a distance, and run in separate Unix processes. This is a compromise in that comunication is more expensive, but the system as a whole is more robust.
[1] http://www.erlang.org/doc/man/erl_nif.html (see "Warning")
[2] http://jlouisramblings.blogspot.com/2013/07/problematic-trai...
[3] http://erlang.org/pipermail/erlang-patches/2011-April/002046...