“We do everything” is a comforting thing to hear from a software vendor and a risky thing to believe. Most software work is well served by a strong generalist team. Some work is not — it needs someone who has spent years inside a specific, unforgiving domain. Knowing which kind of work you have is worth real money. Here is how to tell, and where the line actually falls.
Where a Generalist Team Is the Right Call
For the large majority of projects — web applications, mobile apps, internal tools, APIs, cloud infrastructure, standard integrations — a capable full-stack team is exactly what you want. These problems are well-understood; the risk is in execution, not in exotic domain knowledge. A good generalist team brings broad experience, moves fast, and adapts across the stack. Reaching for a narrow specialist here just adds cost and coordination for no benefit. This is the home ground of general software development.
Where Specialist Depth Genuinely Pays
Some domains punish generalists. They have their own rules, their own failure modes, and consequences that a smart-but-unfamiliar team learns about the expensive way. In these areas, hard-won specific experience is not a luxury — it is what keeps the project out of trouble:
- Building automation and Niagara. Operational-technology systems where a wrong command has physical consequences and the protocols (BACnet, Modbus, Tridium Niagara) are a world of their own. This is SoftwarePile’s field.
- AI agents and MCP. Production AI that acts on real systems fails in ways traditional software does not — hallucination, prompt injection, non-determinism. SoftwareDepo builds these safely.
- Security engineering. When a mistake is a breach, security has to be designed in by people who think like attackers. That is BulletproofSoft.
- Business systems. ERP, CRM, and the integrations between them carry deep process complexity that rewards focused experience — OneStopSoft’s specialty.
- Games and simulation. Real-time engines, physics, and interactive design are their own discipline, handled by SoftwareSplash.
The Test: Consequences and Conventions
A simple way to decide: ask how severe the consequences of inexperience are, and how much domain-specific convention the work carries. If getting it subtly wrong means physical damage, a security breach, or a regulatory problem — and if the field has its own protocols, standards, and hard-earned patterns — you want a specialist. If the risk is ordinary execution risk and the conventions are mainstream, a strong generalist will serve you better and cheaper.
You Shouldn’t Have to Choose in the Dark
The best of both worlds is a partner who covers the general work and can bring in genuine specialist depth exactly when a project needs it — without handing you off to strangers. That is how SoftwareMile is built: full-stack software delivery, backed by dedicated specialist practices for the domains that demand them, under one relationship.
Tell us about your project and we will tell you honestly whether it’s generalist work, specialist work, or a mix — and point you to the right team either way.
Sharpening the Test: Convention, Feedback, and Reversibility
The two questions in the test, how severe the consequences of inexperience are and how much domain convention the work carries, are not equally easy to apply. Consequence severity is usually obvious. Convention depth gets misread, because people check whether documentation exists and stop there. Read that half more narrowly: the conventions that make a field specialist ground are the unwritten patterns, not the published specification. A spec is the part a competent engineer can read. The convention is everything the spec does not say. Which optional fields real implementations actually populate. Which sections of a standard are ignored in the field. What a system does when its own behavior disagrees with its documentation. Which sequences are legal on paper and produce undefined behavior in practice. The load-bearing phrase is hard-earned patterns: a readable standard is the entry ticket, not the depth.
Three further questions separate the cases more cleanly than the domain label does.
- Feedback latency. In ordinary web and mobile work, a wrong assumption produces a stack trace or a red test within minutes. In some domains the same mistake surfaces months later as drifted data, at an interval that only occurs at quarter close, or under a condition you have not encountered yet. When the normal learning loop is that slow, a team cannot learn the domain on your project, which is the real argument for hiring people who already did that learning somewhere else.
- Blast radius past your own process. If the worst case is a bad screen, restart it. If the worst case is a physical action, an irreversible transfer, or a submitted record, the code is not the only thing that has to be right. The operating procedure around it has to be right too, and knowing what that procedure normally looks like is itself domain knowledge that does not appear in any requirements document.
- Reversibility of what you produce. Code is cheap to change. Data already written in the wrong shape, records already submitted, and configuration already pushed to equipment you do not physically control are not. Weight the decision toward depth in proportion to how much of the output is one way.
Where the Obvious Answer Is Wrong
Sounds exotic, is not. Projects get labeled by their industry, and the label quietly does the deciding: a healthcare app, a fintech dashboard, an IoT portal. Do the subtraction before you accept the label. Write down the parts of the system that would be wrong if no domain expert ever reviewed them. Often that reduces to a set of calculations, a list of constraints someone can state in an afternoon, and a vocabulary. Most of the system is ordinary: authentication, a data model, forms, a job queue, reports, an integration with a vendor API. Strip away the domain nouns and what remains is a web application with an API.
Sounds ordinary, is not. Standard integrations and internal tools really are generalist ground, but a few common cases wear that clothing and do not behave like it. An integration with a counterparty you cannot restart, cannot test against, and cannot read the source of is not an ordinary integration; it is reverse engineering on a schedule. An internal tool becomes something else the moment it is the control surface for money movement or physical equipment, because a bad button is now an operational incident rather than a support ticket. A sync is ordinary until you find the remote API has no idempotency key and no way to ask what it already accepted, at which point retry semantics are the whole project. A reporting view stops being a read-only convenience as soon as people act on it, because it is then a second source of truth that has to agree with the first.
Unfamiliar is not the same as deep. Teams often reach for a specialist because a technology is new to them. Unfamiliarity is priced as a learning curve and it ends; depth is priced by what happens when you are wrong and it does not. If the only argument for specialist depth is that nobody in the room has used this before, that is a training and schedule question, not a sourcing decision.
What the Choice Costs You After Go Live
Selection usually gets argued as a build question, but it is also a decision about who can maintain, change, and staff the system for years after handover. Four of those costs are worth pricing before you sign anything.
- Your stack becomes your hiring pool. A specialist team writes in the idioms of its domain: its runtimes, its libraries, its conventions about where logic belongs. That is a good trade when the domain is the system. It is a bad trade when it is a small part of it, because you inherit permanent maintenance in a technology you now have to hire for or keep going back to the original team to touch.
- Undocumented reasoning is the real handoff risk. Domain knowledge tends to arrive in the code as a magic constant, a delay before a second call, a required ordering, or a retry that exists because someone once watched something fail. None of it explains itself. Ask for the reason to be written where the code is rather than in a handoff deck, and treat any unexplained constant as an open question during review.
- Lock-in lives in the data model, not the code. Replacing a service is a project. Changing the shape of data that other systems already read is a program, because every consumer has to move with you. Whichever team owns the schema and the interface contract has more influence over your future options than whichever team writes the most lines.
- Decide who gets paged before go live. A specialist build often carries a runtime, a protocol, or a deployment path the generalist team cannot debug under pressure at three in the morning. Either the specialists stay on call, or the generalist team is trained and given real access well before handover. Both cost something. Finding out after launch that you arranged neither costs more.
How to Test the Choice Before You Commit
You do not have to make this call from proposals and reference calls. Each of these produces evidence before the full scope is committed.
- Probe with a real failure, not a greenfield demo. Give each candidate the same narrow slice whose answer depends on the actual behavior of a system you have to interoperate with, plus whatever documentation you have. The signal is not who finishes. It is who asks about what the documentation does not say, and who tells you in advance where they expect it to be wrong.
- Stub the domain and see whether the system still stands up. Define the domain-specific logic behind an interface and stub it. If a generalist team can build and demonstrate the whole system against that stub, the domain is a component and you can buy depth for that component alone. If nobody can write the stub, because the behavior will not reduce to an interface, then the domain is not separable and the decision is not a component decision.
- Buy review before you buy build. Reviewing a design is a smaller commitment than building the system. Have generalists produce the design and have someone with genuine depth review the decisions that are expensive to reverse: the data model, the interface contract, the trust boundary. Do it early enough that reversing them is still cheap, and set the terms in writing first, so the reviewer's calls on those three are binding or an override is recorded as an accepted risk with a name attached to it.
- Ask each candidate for the three ways this goes wrong. Generalists usually name schedule, scope, and integration surprises, which are true of every project. Depth answers with specific failures and the conditions that trigger them. If both lists come back looking the same, you are not buying depth even if you are paying for it.
The Failure Modes of Each Arrangement
A generalist-only team rarely fails by being unable to write the code. It fails by producing a design that is entirely reasonable and violates a rule nobody wrote down. The dangerous part is when that surfaces. The tests encode the same misunderstanding as the implementation, so nothing turns red, and the problem appears at integration, at first real load, or at the first edge case the domain considers routine.
A specialist-only team fails in the other direction. The ordinary parts of the system get built in the domain's idiom, which makes later routine changes more expensive than they should be, and puts your maintenance inside a narrow skill set. Depth also tends to be thinly staffed, so continuity and availability are real exposures: the schedule follows the calendar of a small number of people, and there may be no second reader for the decisions that matter most.
A mixed arrangement moves the risk to the boundary between the two teams. Both sides build something defensible and the failure lands in between, in the assumptions neither team owns. Write a contract covering schema, error semantics, ordering, and timing, and give that contract a single owner with the authority to settle disagreements, because a boundary owned by both teams is owned by neither. The other mixed failure is the advisory specialist brought in with an opinion and no authority, whose advice quietly loses to schedule pressure.
Frequently Asked Questions
How do I tell deep domain complexity from domain vocabulary?
Count the things you can only know by having been wrong before. Not the specification, which is readable by definition, but the working knowledge outside it: which optional parts of a protocol implementations actually support, which documented behaviors are wrong in the field, what the standard workaround is for a known-broken version, which sequences are legal on paper and unsafe in practice. If that list is short, the domain is mostly vocabulary and a generalist team will absorb it while building. If it is long, that is the hard-earned patterns half of the test, and the work is specialist ground no matter how clear the documentation looks.
What if the depth we need is regulatory rather than technical?
Regulatory depth is a requirements problem before it is a software problem. The constraints have to be turned into testable statements: what must be retained and for how long, who may read what, what must be logged, what must be reproducible after the fact, and what the system must refuse to do. Written that way, a generalist team can implement them. What no team can do is infer them from a line that says the system must be compliant. The exception is where a rule constrains architecture rather than features: data residency, key custody, immutable audit records, or the ability to produce an account of who saw what. Those are difficult to retrofit, so settle them before the data model is frozen.
Can we start with generalists and bring in a specialist later?
Where the domain logic sits behind an interface, yes, and that is a common shape. It gets expensive where the domain constrains decisions made in the first few weeks: the data model, identity and tenancy, how time and ordering are handled, whether operations are idempotent, and where state lives. Those are not features you add later; they are assumptions everything else is built on top of. The practical version is to bring depth in before those decisions are frozen, even if that person writes no code at all, and to buy the build later if you still need it.
How do we evaluate a claim of specialist depth when we are not specialists ourselves?
Ask about failure rather than capability. What broke, how did you find out, what did you change, what do you wish you had known earlier. Depth answers with unglamorous specifics: a version, a vendor quirk, a sequencing rule, a diagnostic they now run first because of something that once cost them a week. Breadth answers with a list of technologies. A second useful question is what they would not take on. A real specialty has edges, and a team that claims none is describing a sales posture rather than a practice.
If we split the work between two teams, where should the seam go?
At a data or protocol interface, not at a feature. Feature splits interleave both teams inside the same code paths and the same release, so every change needs coordination and neither side can test alone. An interface split gives each team an artifact it can build, fake, and verify independently. A good check: if each team can work against a stub of the other for a week without needing a conversation, the seam is in the right place.
Does specialist mean the firm, the individuals, or the tooling?
Ask which, because the three behave very differently after the contract is signed. Tool familiarity is the shallowest form and the quickest for a capable team to acquire. Individual depth is real but travels with specific people, so ask who will actually be assigned, what happens when they are pulled onto something else, and who reviews their work. Practice-level depth shows up as things that outlive individuals: written conventions, checklists derived from past failures, and design review before code ships. For work where being wrong is expensive, the second reader matters nearly as much as the first expert.