Prefork is great if you have about two or three concurrent connections, and if you aren't using a dynamic language like Perl, Python, or Ruby. Otherwise, lightweight threads will serve you better.
One problem that people have (had?) with persistent preforked mod_perl apps is that copy-on-write also copies on reads for certain Perl structures. Say you have "my $foo = 42" and then you fork. The Sv associated with $foo is shared. But when the child says "if($foo eq ...)", the Sv is no longer the same; it's changed from an SvIV to a SvPVIV. No more sharing. (Maybe Python and Ruby are more clever here, but they pay a speed price on non-forked applications for this.)
Eventually you end up with two completely different memory images for the same app instead of the 1 copy of the parent shared with the child.
As for the "about two or three concurrent connections" part, I think you will find that "select" exists for a reason. ("select" is just as much a part of UNIX as "fork", BTW.) If you have a bunch of mostly idle filehandles to read from, select (or rather, its modern replacements) will perform much better than a bunch of forked processes. Imagine you are writing a push messaging server; do you really want one process for each of your 1 million users? No; you want a lightweight thread for each.
(Try this sometime; create 1,000,000 lightweight threads. Then create 1,000,000 processes that do nothing. Then note which one requires you to reboot your computer by yanking the power cable.)