Chris Boyd's side looked like like they were completely out of the game late on as Ben Spencer's two quickfire scores propelled Bath into a 19-point lead.
Saints lost Brandon Nansen to what appeared to be a serious injury before mounting the most unbelievable of late comebacks.
Alex Mitchell's try started the fightback before Tommy Freeman went over for the bonus-point effort.
Bath lost Josh Bayliss to injury, and Jaco Coetzee was yellow carded as Saints were awarded a penalty try.
Saints made one final surge against the 13 men but looked to have lost the chance as referee Luke Pearce signalled a knock-on from Juarno Augustus before Haywood picked up to score.
But it went to the TMO and it was deemed that a Bath hand had dislodged the ball and the try was given, sparking wild celebrations in the Saints ranks.
James Grayson missed the conversion but it mattered not as Saints savoured the most surreal of successes, which moved them into the Gallagher Premiership top four.
It also ended their wait for a win at The Rec, which had stretched all the way back to December 2015.
It was an eventful game throughout and Bath had threatened to come out of the blocks quickly, winning several penalties in the Saints half, allowing them to use their set piece to launch attacks.
Rory Hutchinson had to make a last-ditch intervention, kicking the ball away from the onrushing Bath attackers after Jonathan Joseph had placed a clever chip.
It was soon Bath's turn to earn a sizeable reprieve as Lewis Ludlam broke the home line before trying to offload to Augustus, but the pass wasn't accurate and Augustus agonisingly knocked on with the line in sight.
But Saints kept the pressure on and after Bath struggled to get out, Mitchell provided a tidy try assist for Matt Proctor, who dived over gleefully.
George Furbank converted in windy conditions and Saints had the lead they had hoped for.
But Bath hit back as Mitchell endured a nightmare minute.
The Saints scrum-half booted the ball out on the full before the bounce of the ball beat him inside his own half, allowing the onrushing Max Clark to score.
Danny Cipriani converted and the scores were level 15 minutes before the break.
Furbank had a chance to put his side back in front almost immediately, but he sent his penalty wide from a central position.
Furbank then booted another penalty to the corner but Saints lost the lineout and Bath broke, earning a penalty in the Saints half.
After a period of pressure, the hosts struck, sending wing Will Muir in out wide.
Cipriani converted and Saints were seven points down, having exhibited little control in an error-strewn and indisciplined start to the game.
There were still chances to be had on the break, but Saints weren't taking them.
Freeman launched a counter but Mitchell failed to spot the man inside and kicked ahead, only for the ball to go out of play.
It was yet another moment of pure frustration in a half full of it from a black, green and gold perspective.
Fittingly, the first 40 minutes ended with yet another penalty given against Saints, allowing Cipriani to extend the gap to 10 points as the teams trotted in at the break.
Saints needed a huge improvement after the interval, and they got it as Augustus powered over halfway and put Bath under pressure.
The hosts conceded a couple of penalties before Saints forced their way through, via a trademark Augustus effort.
But Furbank missed the conversion to leave the gap at five points.
And Saints' lack of discipline then continued to bite them, starving them of any sort of momentum and presenting Bath with chances to add to their lead. They soon took them.
First, Spencer broke down the blindside after a maul and dived over in the corner before converting superbly from the touchline.
And the No.9 didn't have to wait long for another score as Freeman failed to gather, the ball went loose and Bath flew forward before Spencer pounced again.
Spencer slotted a second excellent conversion and his side led 31-12, flooring Saints on what was turning out to be a nightmare afternoon.
It was to get worse as Saints were forced to withdraw Nansen just five minutes after he had come on.
There was real concern for Nansen as he was tended to for several minutes and eventually stretchered off to warm round of applause.
Saints scored quickly after the restart, piecing together a move before Mitchell finished with aplomb.
But again the conversion was missed, leaving the gap at 14 points with as many minutes to go.
Saints were starting to play with renewed vigour and a lovely move ended with a fine finish from Freeman, who slalomed his way over for his side's bonus-point score.
Grayson converted and the gap was seven points with 10 minutes remaining.
Saints now had their tails up and after their pack produced a huge shove, referee Pearce awarded a penalty try.
Saints had little more than four minutes to win it with the scores now level.
But win it they did, thanks to Haywood's score, which made sure of the sweetest of triumphs.
Orlando Bailey was yellow carded to compound Bath's last-gasp agony on an afternoon when it looked like they would secure their fifth league win of the campaign.
Bath: De Glanville (Cokanasiga 53); Rokoduguni, Joseph, Clark; Muir; Cipriani (Bailey 48), Spencer (Simpson 70); Morozov (Cordwell 70), Dunn (du Toit 66), Stuart (Rae 63); Williams (Richards 62); Ewels (c); Bayliss, Reid (Coetzee 66), Faletau.
Saints: Freeman; Sleightholme, Proctor (Grayson 60), Hutchinson, Collins (Francis 58); Furbank, Mitchell; Waller (Iyogun 55), Matavesi (Haywood 60), Hill; Coles, Ratuniyarawa (Nansen 58 (Moon 63)); Ludlam (c), Harrison, Augustus.
Referee: Luke Pearce