> Most code I write doesn't do anything interesting, it's either some boilerplate or glue for connecting subsystems together.
That's your fault. There's not some line where "interesting code" lives on one side and "boring glue code" lives on the other. I agree that you don't want boring glue code, but you also don't want highly interesting code either! Every block of code should be "mildly interesting": doing about one interesting thing. Your job is to evenly spread the intrinsic complexity of the problem over code blocks to make this happen. If you're writing boring glue code that doesn't solve part of the problem interspersed with highly interesting code that handles 15 different cases, your code is lumpy!
So many people talk about spending too long on boilerplate glue code, but you're stitching this part and that part of the code together for a reason -- for a reason that can be expressed in domain logic and user stories -- right? (If not, you truly are wasting your time, but that's only because that whole code block doesn't deserve to exist.) So express the reason for stitching that code together in the glue code, and now it's mildly interesting, just like all of your code should be.
It blows my mind that the same people who complain about over-abstraction also complain about spending too long in the weeds of boilerplate code. You're so used to bad abstractions that you've given up, and then you whine "why can't I do this at a higher level!?" Because you've stopped trying, that's why! Learn to write better abstractions, and keep tweaking them when they become awkward. Finding a good abstraction is really hard, but absolutely worth it when it happens. And there are meta strategies you can learn to make it easier.