I don't agree that TH is bad. It's bad for generating real code (like I wouldn't use it to generate complicated logic), but just like you don't write Eq,Show,Ord instances yourself and instead let the compiler derive them for you, you use TH to generate JSON instances. I see TH more as a extension of deriving so I can easily derive custom typeclasses than for generating real code.
For Aeson instances you really should be using the Generics. I do agree though that there are useful libraries (AcidState/SafeCopy is one example) that cannot reasonably be used without TemplateHaskell. While TemplateHaskell should be avoided if possible, it isn't the only consideration in choosing a design and dependency tree.
The article does not go into detail why TH is bad, and neither do you. Why should I be avoiding it? What are the exact problems with it, except the occasional breakage with new GHC releases?
Generics is also not without its faults (it inflates compile time/memory, for example, see problems surrounding aeson 0.10). If the article is correct when it says that /[TH is] a eternal source of pain and sorrow/, then you're trading one pain for another.
As a maintainer of a >130kloc Haskell codebase spanning thousands of modules and hundreds of packages, I avoid TH primarily for one reason: slow builds. Painfully slow.
For cases where GHC.Generics is an option, I always take GHC.Generics over TH. Yes, Generics can be slow at times too but this somewhat controllable with various GHC_OPTIONS. Either way, there is no loader and interpreter overhead... and a lot of Generics code compiles in less time than it takes TH just to load `text` or `aeson` ;-).
Other reasons:
* Some TH libraries add implicit dependencies that are not tracked by the build system
* GHCi/TH's loader is different than the OS loader, sometimes causing failures if a TH dependency touches C++ libraries
* No cross compiling ability... not an issue for me but it's painful for those targeting Javascript (via ghcjs), ARM or smaller x86 embedded systems
This case seems to increasingly be handled by DeriveGeneric. I realise the performance isn't quite the same, but so far my experiences of GHC generics have been pretty positive.
What's the performance overhead of instances based on Generic instead of TH? In PureScript for example generic instances are so slow it makes them unusable.