Three Portland city councilors held on to their seats Tuesday – one just barely – after all the votes were finally counted early Wednesday morning.

At-large Councilor Nicholas Mavodones narrowly held off a challenge from Joey Brunelle, by a margin of 702 votes out of 28,970 cast. Mavodones got 14,836 votes and Brunelle received 14,134. Brunelle said Wednesday he’s looking into whether he can and should request a recount.

District 1 Councilor Belinda Ray and District 2 Councilor Spencer Thibodeau easily won their races for re-election.

Ray, a 48-year-old freelance writer and accounts and administration manager for a local building company, received 70 percent of the vote to defeat Matthew Coffey and win a second term. Ray got 3,770 votes and Coffey got 1,589.

Thibodeau, a 30-year-old real estate attorney finishing his first term, got 68 percent of the vote in District 2 to beat Jonathan Torsch. Thibodeau won with 4,081 votes to 1,963.

Brunelle led the race Tuesday night, but unusual delays in Portland’s vote-counting process meant nearly half of the city’s precincts did not report results until about 6 a.m. Wednesday. Mavodones, a 58-year-old operations manager at Casco Bay Lines, finished strong in the city’s more suburban neighborhoods, winning an eighth term on the council.

Mavodones found himself in the unusual position of going to bed not knowing if he had won.

“I have never been in such a close race – this was right down to the wire,” he said Wednesday. “I thought it was going to be close. I will say it was a little closer than I expected.”

Brunelle had campaigned throughout the city for most of the past two years. He placed second last year, behind incumbent Jill Duson, in a three-way race for an at-large seat on the council.

“You have to give him credit,” Mavodones said. “His name is definitely becoming well-known in the community.”

Brunelle said in a text message Wednesday afternoon that he was consulting the city clerk and an attorney about whether to request a recount.

“We ran an incredible, principled campaign, and we are disappointed with the result,” he said. “But because we saw such unprecedented turnout that caused ballot counting to go into the early morning, we are currently investigating the possibility of a recount to ensure the result is accurate.”

Mavodones is one of the more fiscally conservative and business-friendly councilors, while Brunelle ran a progressive campaign that included a call for a carbon tax on large industrial and commercial businesses, including cruise ships, and more aggressive policies to protect middle- and low-income families from being priced out of the city.

Mavodones had a significant fundraising advantage over Brunelle, who did not accept money from real estate developers, out of state donors or political action committees. Mavodones raised over $35,000, allowing him to send direct mail and hire a Pittsburgh firm to operate a phone bank the weekend before the election. He also got some unwelcome help from the National Realtors Association, which made an independent expenditure of $7,300 for online ads – a move decried by both Brunelle and Mavodones.

Brunelle, meanwhile, raised just over $5,500.

Portland voters also overwhelmingly approved a city charter change to require municipal candidates to file an additional campaign finance report. The ballot question passed with 75 percent of the vote, 20,229 to 6,621.

Currently, local candidates only have to report their campaign finances in July (if they are active) and 11 days before the election. Question 2 on the municipal ballot adds an additional report 42 days before the election, a requirement that already exists for state candidates.