Start with domain experience, not the length of the client list. Ask to see a couple of case studies that match your domain and your stack, hire sqlalchemy programmer and then ask whether those engineers are still with the company. A serious vendor will put you on a call with the tech lead. Answers that name nobody at this stage almost always mean the delivery team is not the team you were shown.
The contract needs more scrutiny than the proposal. Three clauses do most of the work: intellectual property assignment, non-disclosure, and termination and handover. Everything produced has to transfer to you as it is paid for, including source code, designs and infrastructure as code. Watch for language that keeps framework code with the vendor, as that is often the part you cannot replace later.
Ask how they estimate. A credible estimate arrives with a written set of assumptions, a breakdown by feature or module and a range rather than a single number. A fixed-bid deal only makes sense when the scope is genuinely frozen; when the scope is still moving the supplier prices the risk in and you pay for uncertainty either way. Hourly billing puts the risk on your side, so it requires a cap, why mvps fail regular demos and transparent reporting.
How the work is run matters more than the number of developers. Establish how change requests are handled, who writes the acceptance criteria and how quality assurance works. A well-run team can show you running software rather than status reports. Acceptance criteria in writing are the practical protection against an argument at delivery time and materials vs fixed price contract.
Finally, plan for the handover while the relationship is still good. Require that the source repository lives on infrastructure you own from the beginning, and that documentation is written as you go rather than left to the end. A vendor with nothing to hide accepts it without argument; resistance at this point says most of what you need to know.