I'd strongly recommend keeping this in signal domain if you want to do this via normal IIR filter. MSP has some pretty efficient filters, such as onepole~, and IIR filters are a pain to implement correctly, since you have to be aware of things like denormal numbers.
If it's sensor data, however, I'd use slide~ (there's slide in control rate as well, but you'd need to be feeding it at a steady rate) or rampsmooth~, or if it's coming in at control rate, use line or line~ to smooth it out. Slide~ is almost obscenely efficient, btw.
If something needs very regular processing (e.g. it's calculated > 20 times a second), I recommend doing it in signal domain. It's pretty efficient, and if you want to save CPU on these types of control processes, you can always downsample with poly~. (I routinely downsample my LFOs by a factor of 16.)
If you're scheduling a bunch of events in the controller thread, the scheduler gets unhappy, and then you lose timing precision (not so with signal domain!) --which your IIR coefficients are dependent upon! You also don't really have an accurate sense of how much CPU the scheduler itself is using, so there can be problems with spikes.
In general, my rule of thumb is don't use control-rate to do things more efficiently than signal rate. It blocks up your scheduler thread for more important things, and usually isn't worth the trouble.
Either Line or slide would work if you really want to avoid signal rate. (interpolation = lowpass filtering)
You can find formulas for various biquad filters here:
Looks like the denormal thing doesn't matter w/ Max. Good to know. (is there anything internal to Max that does that?)
I personally prefer slide, since you get the benefits of asymmetry in attack/decay if needed. Really depends on what your signal looks like. For things that are similar to a percussive attack, having a fast attack + long decay often works pretty well.
Bit of a wild hair here, but you could also pretty easily implement an FIR filter via zl.stream, vexpr, and zl.sum. Could be interesting to use a window function with that.
I just uploaded C code I wrote 10 years ago that does IIR processing. (Sorry I didn't do this sooner. I was wrapped in a PHP object and couldn't get out.) It most certainly needs updating and I'll get to that as soon as I can. It's at: https://github.com/diskerror/MAX