Software development as an engineering discipline
The hard part of software is never the first version. It is the fourth change request, made by someone who was not in the original conversation, against code the original author has left. Everything we do about architecture, tests and documentation is aimed at that moment.
What the work consists of
Software development is the whole path from an ambiguous business problem to a running system somebody depends on: understanding the domain, choosing an architecture proportionate to it, modelling the data, writing and reviewing the code, testing it, deploying it repeatably, and operating it once real users arrive.
The discipline is mostly about restraint. Almost every serious failure we are asked to rescue was caused by something being more clever than the problem required a distributed architecture for one server's worth of traffic, an abstraction built for a second use case that never arrived, a framework chosen because it was new. Boring, well-understood technology applied carefully outperforms novelty almost every time.
What we provide
Application architecture
Choosing the shape of the system where boundaries go, what is synchronous, what can fail independently sized against the load and the team you actually have.
Backend systems
Business logic that lives in one place, service layers with clear responsibilities, and jobs, queues and scheduled work for the things that must not happen inside a request.
APIs
Versioned, documented interfaces with consistent error handling and idempotency on writes designed so a second consumer does not force a redesign.
Databases and data modelling
Normalised where correctness matters and denormalised where reads demand it, with the trade-off written down rather than discovered.
Integrations
Payment providers, CRMs, ERPs, messaging and third-party APIs with retries, backoff, webhook verification and a plan for the day the other side is down.
Legacy modernisation
Incremental replacement of systems that still work but have become expensive to change, without a big-bang rewrite that stops delivery for a year.

Who we do this for
Businesses whose processes have outgrown their tools
Where the workaround has become the process, and the spreadsheet has become the database.
Companies with software they cannot safely change
A system that works but that nobody dares touch is a liability accumulating interest.
Teams that need engineering capacity, not headcount
A partner who can own a piece of the system end to end, including the parts that are not fun.
What this solves
Every change breaks something else
Logic duplicated across layers with no tests to catch the divergence. The fix is not a rewrite; it is characterisation tests and consolidation, one behaviour at a time.
The system cannot be reasoned about
No documentation, no types, no consistent conventions. Making it legible is cheaper than replacing it, and it is the prerequisite for deciding whether replacement is even warranted.
Integrations fail silently
Fire-and-forget calls with no retry, no dead-letter handling and no alerting, so a partner outage becomes missing data discovered weeks later.
Only one person can deploy it
Undocumented manual steps are an availability risk disguised as a process. Automating them is usually a few days' work and removes a genuine single point of failure.
How we work
- Step 01
Understand the domain first
Time with the people who do the work today, including the exceptions they handle manually. The exceptions are where the real requirements hide.
- Step 02
Choose the least clever architecture that works
Complexity is a permanent cost paid by everyone who touches the code afterwards. It has to be earned by a requirement, not chosen by preference.
- Step 03
Make it observable early
Logging, error tracking and metrics before the first real user, so the first production surprise is diagnosable rather than theoretical.
- Step 04
Hand over properly
Repository, documentation, runbooks, architecture decisions with their reasoning, and access to every account. Nothing about the system should depend on us being reachable.
What we build with
Languages
- JavaScript
- TypeScript
- SQL
Runtime
- Node.js
- Serverless functions
- Background jobs
Data
- PostgreSQL
- SQL Server
- Document stores
- Blob storage
Practice
- CI/CD
- Automated testing
- Code review
- Monitoring
This list is what we actually work in, not a catalogue. Where a project needs something outside it, we will say so rather than learn it on your budget.
The parts nobody demos
Security, performance, deployment, testing and maintenance decide whether a project is still working in two years. They are scoped in from the start rather than quoted as extras.
Security
Threat-modelled at design time rather than audited at the end: validation at every trust boundary, least-privilege service identities, secrets managed by the platform, dependency scanning in CI, encrypted data in transit and at rest, and audit logging on anything that changes money, permissions or personal data.
Scalability
Understanding where the load actually is before optimising for it. Caching, indexing and asynchronous processing applied where measurement says they are needed, and horizontal headroom designed in even when it is not yet used.
Testing
Automated tests on the logic that would be expensive to get wrong, integration tests at system boundaries, and a full build and test run on every pull request. Tests are documentation that cannot go stale.
Cloud deployment
Reproducible environments, deployment as an automated pipeline rather than a procedure, and rollback as a first-class operation rather than an emergency improvisation.
Maintenance
Scheduled dependency updates, monitoring and alerting configured at launch, and an architecture decision record so the next engineer inherits the reasoning as well as the code.
What people come to us with
- Replacing a manual process that has become a bottleneck or a risk
- Building the backend and integrations behind an existing product
- Modernising a working but unchangeable legacy system incrementally
- Connecting systems that currently exchange data by export and re-import
- Adding engineering rigour tests, CI, monitoring to a product built at speed
Where we have done this
Builds where this capability carried real weight. Each case study describes what was actually engineered.
Software Development questions we get asked
Web development is a subset software delivered through a browser. Software development is the wider practice: the same engineering applied to backends, integrations, data pipelines and internal systems that may have no interface at all. Most of our work is delivered on the web, but the discipline behind it is not web-specific.
On the logic where a defect would be expensive, and at system boundaries. We do not chase a coverage percentage tests written to satisfy a metric tend to test implementation rather than behaviour, and they make refactoring harder rather than safer.
Make it observable before changing it. Logging and characterisation tests that pin down current behaviour come first, so subsequent changes have something to fail against. Rewrites are the last option, not the first, and they are proposed with a migration path rather than a big-bang date.
That is a normal and healthy outcome. Everything repository, infrastructure, accounts, documentation is yours throughout, and handover to an internal team is a planned piece of work rather than a negotiation.
Thinking about software development?
A short conversation is usually enough to tell you whether this is a week of work or a quarter of it and whether you should be building it at all.


