Technology
A stack is a set of decisions, not a list of logos.
Anyone can list these. What is worth reading is why each one is here, what it is deliberately not used for, and where we will tell you it is the wrong choice for your estate rather than the right one for our comfort.
Platform & Language
- .NET
- C#
- Python
- TypeScript
- Node.js
We choose technology your systems can live with for ten years, not what is fashionable this quarter. An operations console commissioned this year will be maintained by people who have not met us, on a platform that will still be supported and still be hireable for. That is a boring argument and it is the correct one. Python goes where the AI and data work is, TypeScript everywhere the browser is involved, and we do not add a fourth language to a project because someone on the team wanted to learn it.
Web
- React
- Next.js
- SignalR
The point of this row is pages that arrive fast and live numbers that stay live. Next.js because rendering on the server is the default we want, not an optimisation we retrofit — most of what we build is read far more than it is interacted with. SignalR carries the live half: a drilling parameter, a delivery receipt, a translation channel's delay. When a number on screen is stale, someone acts on the stale number.
Mobile
- Flutter
- Android
- iOS
Flutter is our default for operational apps — one codebase, one design system, and the platform differences that actually matter handled explicitly rather than pretended away. We go native when the system needs the platform itself: background location, specific hardware, deep OS integration. That decision is made per system and written down, because the wrong answer is expensive in both directions.
AI
- Semantic Kernel
- OpenAI
- Azure OpenAI
- LLMs
- RAG
- vector search
AI gets used where it helps and fenced in where it would guess. We treat the model as a component with a failure mode, not as the system: it gets a tool boundary, a lookup step it cannot skip, and a set of questions with known answers that runs on every change — because 'it seems better' is not a claim anyone should deploy on. Azure OpenAI where the deployment needs the model in a specific region under a specific agreement, which for enterprise work is most of the time.
Data
- PostgreSQL
- SQL Server
- Redis
PostgreSQL by default. Most systems that were given a document store because they might need to scale would have been better served by a relational database and a schema someone thought about — the flexibility bought at design time is paid for at query time, forever. SQL Server where the estate is already there. Redis is a cache and a queue, and it is never the only copy of anything.
Cloud & Runtime
- Azure
- AWS
- Docker
- Kubernetes
- CI/CD
Azure is our primary cloud and AWS is a first-class alternative, and which one you should use is decided by where your data is allowed to live and what your estate already runs — not by which one we prefer. Kubernetes when the operational complexity buys something real; we will tell you when it doesn't, which is more often than the industry admits. If it was configured by hand, it does not exist.
Protocols & Integration
- WITSML
- SRT
- RTMP
- REST
- gRPC
- OAuth 2.0
- webhooks
This row is the one that is hard to fake. WITSML 1.4.1.1 and 2.0 because drilling telemetry has a standard and the standard is not optional. SRT because venues have the network they have and RTMP over a lossy link degrades where the audience can see it. Everything here assumes delivery fails: duplicates are non-events, failures retry on their own, and both sides are checked against each other — so a message arriving twice changes nothing and one that never arrives is visible to someone rather than discovered by a customer.
The right answer depends on what you already run.
Where your data is allowed to live, what your team can maintain, and what is already in the estate decide more of this than our preferences do. Tell us what you have.