Miami committed two errors and was unable to convert on the necessary plays with the game on the line, which proved to be the difference.
"We've got to play defense," Marlins manager Mike Redmond said. "We had a couple opportunities to make some plays and didn't, and it cost us."
Jordany Valdespin delivered a pinch-hit home run for the Marlins, who have dropped three straight to fall to 65-68. Miami is 2-5 on the road trip, and the team sits six games behind the Cardinals for the second Wild Card spot.
"You don't want to say you have to play mistake-free baseball," Miami starter Tom Koehler said. "But every mistake right now is going to be magnified, because we're playing for something. I'm not going to sit here and say, 'Oh, we lost today, now we're out of it, we're done.' As we've shown all year, we're going to come back tomorrow and keep battling."
Momentum swung in Atlanta's favor in the bottom of the seventh inning. With the game tied at 2, Andrelton Simmons dropped a bunt single against Chris Hatcher, and pinch-hitter Ramiro Pena was awarded a single on a line drive that went off Garrett Jones' glove at first base. The hit put runners on the corners with no outs, and had Jones wondering what happened, because he likely would have been able to turn a double play.
"I thought I had it," the Marlins first baseman said. "I thought it went right in the glove, and somehow it rolled out. I thought it might have gone through the webbing, because it kind of felt like it had hit the meat of the pocket."
Lefty Mike Dunn relieved Hatcher to face Heyward, who chopped an RBI single on a grounder just past shortstop Adeiny Hechavarria, who was playing in.
"I was just going up there and trying to keep it simple," said Heyward, batting .375 (21-for-56) against Miami this year. "At that point, we're trying to put the ball in play wherever it is and not do too much."
Sam Dyson, Miami's third pitcher used in the inning, allowed an RBI single to Upton, who swatted the ball up the middle with the count full. A second run scored on center fielder Marcell Ozuna's error.
Miami led, 1-0, in the sixth inning before Koehler gave up a two-run homer to Upton.
"The team did a great job battling and getting me a run," Koehler said. "To just give it back like that, I put this game on me. That's a big zero right there. Who knows? [With] the momentum we carry back into the dugout, and maybe we get some more runs after that. It's just unfortunate."
Atlanta cashed in on Koehler's leadoff walk to Freddie Freeman, who drew a free pass after being down 1-2 in the count. On a 1-1 pitch, Upton laced a no-doubt, two-run homer to center. It was the Atlanta slugger's 26th shot of the season, and it helped up his RBI total to 91 by the end of the night.
Miami tied it at 2 in the seventh inning on Valdespin's pinch-hit home run, an opposite-field shot to left.
The game had been scoreless until the sixth inning, when Ozuna hit an RBI double that remained just fair inside the right-field line. Casey McGehee got the inning rolling with a single, and he moved to second on Jones' single.
McGehee scored easily on Ozuna's double, but Jones was thrown out at the plate by second baseman Tommy La Stella, who relayed Heyward's throw from the wall.
"You know coming in here that runs are going to be tight and every play is going to count," Redmond said.