The Mexican took the chequered flag 7.5sec ahead of the Ferrari of Charles Leclerc.
However, he had to endure a nervy few hours before his victory was confirmed when he was penalised five seconds for a safety car infringement.
Carlos Sainz was third to make it a double podium for Ferrari in the night race that started more than an hour late because of a storm.
It was the first grand Prix to be held under lights at the Marina Bay Street Circuit since 2019 because of the coronavirus pandemic.
Verstappen had a mathematical chance to clinch a second world title, but needed to win and have other results go his way. He finished seventh after a rollercoaster race.
The Dutchman was always going to struggle after starting eighth on the grid and his task was made trickier by an early evening deluge that delayed the start till 9:05 pm (1305 GMT).
When the field eventually tore away from the grid in a shower of spray, Verstappen almost stalled and dropped back from eighth to 13th.
The 25-year-old cut through the field before flat-spotting his tyres trying to pass Lando Norris for fourth after a safety car restart.
"I was up with Lando and as soon as I braked, the front wheels jumped in the air and I went straight on," said Verstappen who was forced to pit for fresh rubber and dropped to last place.
"It's not what I'm here for. Not with a car like that. It was incredibly messy."
It means his world championship lead over Leclerc has been cut to 104 points ahead of next week's Japanese Grand Prix. Perez is two points behind Leclerc.
Verstappen will need to be 112 points ahead at the end of next Sunday's race in Suzuka to retain his title and can do so if he wins and Leclerc fails to finish second.
Leclerc started on pole but Perez slipped past before the first turn and drove a perfect race to hold off the Monegasque for his second GP win of the season.
"It was certainly my best performance," Perez said. "I controlled the race. The last three laps were so intense. When I got out of the car, I felt it. I gave everything today."