Skip to main content
The tools we build with

A deliberately boring technology stack, chosen so your software still works in ten years

Every tool listed on this page was picked for the same reason. It has a long history, a large community, documented upgrade paths and enough people who know it that you will never be trapped. Fashion is expensive in software, and the client always pays for it eventually.

Why the choice of technology matters more than it seems

Clients often tell us they do not care what the software is written in, and in one sense they are right. Nobody buying a booking system cares which framework produced it, as long as it books things. The reason the choice matters is what happens afterwards. Technology decides how expensive your third year is, how easy it is to hire someone else if you need to, whether a security patch is a routine update or a rewrite, and whether the system can grow when your business does.

We have watched the industry cycle through many fashionable frameworks since 2008. Some became foundations. Most were abandoned by their creators within a few years, leaving the companies who adopted them stranded with software nobody wanted to touch. That experience made us conservative in a very specific way. We are happy to use new tools inside a project, but the load bearing parts are always things with a proven record of surviving.

What follows is the actual stack behind our work, including our own production platform. It is not an aspirational list of everything we have read about. These are the tools we use daily, know deeply and are willing to be responsible for at three in the morning.

Python and Django

Python is our primary language and Django is our primary framework. Django arrives with security defaults already in place, an administration interface that saves months of work, a mature migration system for evolving databases safely, and a user and permission model that suits almost every business system we are asked to build.

The practical benefit is that we spend our hours on the part that is specific to your company rather than rebuilding foundations that every application needs. The strategic benefit is that Django has been maintained for many years by a large community with a published release and support policy, so an application written today has a documented path forward for a long time.

Django REST Framework sits alongside it for interfaces, giving us serialisation, authentication, permissions, throttling and browsable documentation without inventing anything unusual that a future developer would have to decode.

MySQL, Redis and Celery

MySQL holds the data that must never be lost. We design schemas properly, use foreign keys and constraints rather than hoping the application layer behaves, add indexes based on the queries the system will actually run, and plan for the volume the table will hold in five years rather than five weeks.

Redis handles caching and session storage, which is usually the fastest single improvement available to a slow application. Expensive queries and rarely changing pages get cached with sensible expiry rules, and the difference on a busy system is measured in whole seconds.

Celery runs the work that should never block a page. Sending thousands of notifications, producing large reports, processing uploads, calling slow external services and running scheduled nightly tasks all happen in background workers. The user clicks a button, gets an immediate response, and the heavy lifting happens where nobody is waiting.

Kotlin, SwiftUI and Firebase

Mobile applications are written natively. Kotlin for Android and SwiftUI for iOS give us applications that feel correct on each platform, start quickly, behave well on older hardware and respect battery and mobile data. Users notice the difference even when they cannot explain it.

Both applications talk to the same REST API, which means one set of business rules rather than three implementations that slowly drift apart. Firebase Cloud Messaging delivers push notifications reliably to both platforms without us building notification infrastructure from scratch.

We also handle everything around the code, including store listings, screenshots, privacy declarations, review responses, staged rollouts and the ongoing obligation to keep published applications compatible as each platform raises its requirements.

Linux, NGINX and Gunicorn

Production applications run on Linux servers we configure ourselves. NGINX sits at the front handling connections, static files, compression and certificates. Gunicorn runs the Django application behind it with a worker count matched to the machine. Systemd keeps services running and restarts them if they fail.

Around that core sits everything that separates a real deployment from a hopeful one, such as firewall rules, automatic certificate renewal, log rotation, fail counting on login attempts, scheduled offsite backups and monitoring that alerts us rather than your customers when something stops responding.

We can deploy to a virtual private server, to a cloud provider or to infrastructure you already own. What we insist on is that the configuration is documented and reproducible, so rebuilding the environment is a known procedure rather than an archaeology project.

Artificial intelligence platforms

We integrate large language models into production applications using platforms including Claude and DeepSeek. The model is the easy part. The work that matters is everything around it, including giving the model access to the right internal data, constraining what it is allowed to do, handling the cases where it is uncertain, logging what it produced and making sure a human can step in.

We build assistants that answer questions from your own documents, classifiers that route incoming work, drafting tools for repetitive correspondence and agents that carry out defined multi step tasks inside your system. We are equally willing to tell you when a simple rule would do the job better and cheaper than a model.

Front end and integration

On the browser side we favour clean HTML, modern CSS and the amount of JavaScript the job genuinely needs. Bootstrap gives us a responsive grid and accessible components without a heavy build pipeline, which keeps pages fast and keeps the code readable by whoever inherits it. Where an interface truly requires a rich client, we build one, but we do not impose that complexity on a site that does not need it.

Integration work covers payment providers, email delivery services, SMS gateways, accounting packages, mapping and location services, calendar systems, document storage and any documented third party API. If a system you rely on offers an interface, we can usually connect it to the software we build.

At a glance

The complete toolkit

Everything we work with regularly, grouped by where it sits in a system.

Languages

PythonKotlinSwift JavaScriptSQLHTMLCSS

Frameworks

DjangoDjango REST FrameworkSwiftUI BootstrapCelery

Data

MySQLRedisSQLite Database designQuery tuningMigrations

Infrastructure

LinuxNGINXGunicorn SystemdSSL and TLSVPSDocker

Services

Firebase Cloud MessagingEmail APIsSMS gateways Payment providersThird party APIs

Artificial intelligence

ClaudeDeepSeekLLM integration AI chatbotsAI agentsRetrieval

Questions clients ask about our stack

Yes, and that is a deliberate design goal. Python and Django are among the most widely used tools in web development, and we write conventional code rather than clever code. Any competent Django developer can read our work, which is exactly the situation you want to be in if you ever need to move on from us.

Cross platform tools have improved and they suit some projects. We prefer native Kotlin and SwiftUI where the application matters to the business, because performance on older devices, integration with platform features and long term store compatibility are all better. We will happily discuss the trade off for your particular case.

Usually. We have taken over sites and applications built in a variety of technologies, and the first step is always an honest assessment of what is there. Sometimes we maintain it as it is, sometimes we add a new component alongside it, and occasionally we recommend rebuilding, with reasons you can weigh yourself.

We use Docker and scripted deployment where it genuinely helps, particularly on larger systems and where several environments must match. On a small site it can add more complexity than value, so we choose based on the project rather than applying the same pattern everywhere.

Versions are pinned so that deployments are repeatable, and updates are applied deliberately on a schedule with testing rather than automatically in production. Security advisories are handled promptly, and larger framework upgrades are planned as small pieces of work well before the old version stops receiving support.

Not sure which technology suits your project?

Describe what the software needs to do and we will explain, in plain language, what we would build it with and why. The recommendation is the same whether or not you hire us.