Here at QCon, well-known Java developer Cameron Purdy gave a fun talk called "10 Ways to Botch Enterprise Java Scalability and Reliability". (He also gave this talk at JavaOne.)
While I could quibble with Cameron's counting---there were actually more like 16 points thanks to some numerical overloading---I liked his content. He echoes many of the antipatterns from Release It. In particular, he talks about the problem I call "Unbounded Result Sets". That is, whether using an ORM tool or straight database queries, you can always get back more than you expect.
Sometimes, you get back way, way more than you expect. I once saw a small messaging table, that normally held ten or twenty rows, grow to over ten million rows. The application servers never contemplated there could be so many messages. Each one would attempt to fetch the entire contents of the table and turn them into objects. So, each app server would run out of memory and crash. That rolled back the transaction, allowing the next app server to impale itself on the same table.
Unbounded Result Sets don't just happen from "SELECT * FROM FOO;", though. Think about an ORM handling the parent-child relationship for you. Simply calling something like customer.getOrders() will return every order for that customer. By writing that call, you implicitly assume that the set of orders for a customer will always be small. Maybe. Maybe not. How about blogUser.getPosts()? Or tickerSymbol.getTrades()?
Unbounded Result Sets also happen with web services and SOAs. A seemingly innocuous request for information could create an overwhelming deluge---an avalanche of XML that will bury your system. At the least, reading the results can take a long time. In the worst case, you will run out of memory and crash.
The fundamental flaw with an Unbounded Result Set is that you are trusting someone else not to harm you, either a data producer or a remote web service.
Take charge of your own safety!
Don't get hurt again in another dysfunctional relationship!