Look first at relevant experience, not the length of the client list. Request two or three engagements that match your domain and your stack, and then find out who actually wrote that code. A solid partner will introduce you to the tech lead. Answers that name nobody at this stage generally mean the demo work came from somewhere else.
The contract needs more scrutiny than the proposal. Three clauses do most of the work: ownership of the code, non-disclosure, and exit terms and handover. Everything produced should transfer to you as it is paid for, ongoing software support company along with documentation, fastify vs laravel pipelines and deployment scripts. Look closely at language that leaves reusable components outside the transfer, since this is frequently exactly the piece that locks you in.
Ask how they estimate. A serious estimate is accompanied by a written set of assumptions, a breakdown by feature or module and an explicit range. A fixed-bid deal works only when the specification is complete; otherwise the provider adds a risk premium and you fund the buffer regardless. Time and materials shifts that risk to you, so it requires a sprint cadence, demos and a budget cap.
How the work is run matters as much as team size. Ask how a new requirement enters the plan, who writes the acceptance criteria and how quality assurance works. A mature team will be able to walk you through a live build at the end of each sprint. Clear, written acceptance criteria remain the only reliable protection against an argument at delivery time.
Finally, plan for the day you no longer need this vendor while the relationship is still good. Insist that the repository sits in your organisation from the first commit, and that the documentation is refreshed in every sprint. A partner who is comfortable with this will agree quickly; hesitation here reveals quite a lot.