Security questions tend to arrive late in a project, usually as a questionnaire from someone's IT department a week before launch. By then the answers are already decided, by choices made months earlier about how the system was put together.
So we think about security from the first conversation, and we think about it in layers. No single layer is perfect. Each one is built on the assumption that the one in front of it might fail, so a single mistake doesn't turn into a breach. Here's how that works, from the ground up.
Start with who would want in
Before any code, it's worth asking a plain question: who might attack this, and what would they be after? A booking system for a small team, a portal holding customers' personal details, and a shop taking orders all have different answers. Knowing which data matters most tells us where to spend the effort, and stops us gold-plating the parts that don't need it.
Foundations: the data centre
The physical layer is one we're happy to leave to the experts. We host with leading cloud providers such as Microsoft Azure, whose data centres are certified to international standards like ISO 27001 and audited far more often than any single company's server room could be. Power, cooling, physical access and hardware failure are their problem, and they're very good at it. For UK clients we keep data in UK or EU regions.
The network: everything encrypted in transit
Every connection to the systems we build uses HTTPS, so nothing travels in plain text, and browsers are told never to fall back to an unencrypted connection. Connections between the application and its database are encrypted too.
We also keep the doors few and narrow. The database isn't reachable from the open internet, other websites can't call the application's interface unless we've deliberately allowed it, and repeated attempts from the same source are slowed down or blocked before they become a problem.
The application: untrusted by default
Everything that arrives from outside is treated as untrusted until it's been checked: form fields, uploaded files, links, even data from systems you already run. In practice that means three habits.
- Check everything on the server. Checks in the browser make forms friendlier, but anyone can switch them off. Every rule that matters is enforced again on the server.
- Never let data become code. Text a user typed is shown as text, never run as part of the page or a database query. That closes off the two oldest tricks in the book: cross-site scripting and SQL injection.
- Tell the browser what's allowed. A content security policy lists exactly where a page may load scripts from, so even if something slipped through, the browser would refuse to run it.
We use the OWASP Top 10, the industry's list of the most common web application weaknesses, as a shared checklist, so these aren't left to memory.
Who can do what
Signing in is the start, not the end. Most business systems have people who should see some things and not others: staff who can view orders but not refund them, managers who can approve, customers who must only ever see their own records.
We build those rules as roles and permissions, and check them on the server for every request, not just by hiding buttons. The same idea applies inside the system: each part gets only the access it needs. The application's own database account can read and write its data, but it can't change the database's structure or reach anything else.
Passwords are stored as salted hashes, never as text anyone could read back, and we recommend two-factor sign-in for anyone with administrative access. If your organisation already signs in with Microsoft 365, single sign-on is possible too, though it's entirely optional.
The architecture: hold less, so you can lose less
The most secure data is the data you never hold. Card payments go straight to a payment provider, so card numbers never touch your system at all. We collect only the personal information a process actually needs, and agree how long it's kept.
Passwords, API keys and other secrets live in the hosting platform's secure settings, never in the code. Each environment (development, testing and live) has its own, and live data stays in the live environment. Connections to other services use their modern, revocable sign-in methods rather than shared passwords, so access can be withdrawn without changing anything else.
No single layer is perfect. Each one assumes the one in front of it might fail.
The database: encrypted and backed up
Data is encrypted at rest, so a stolen disk or backup file is unreadable on its own. Backups run automatically and are kept for a set period, with point-in-time restore, so we can wind the database back to just before a mistake rather than to last night.
A backup you've never restored is only a hope, so we test restores. We'd much rather find a problem on a quiet Tuesday than on the day it matters.
Keeping it up to date
Much of any modern application is built on other people's code: frameworks, libraries and packages. That's a strength, but every package is something that can need a security fix. We keep them current, watch for published vulnerabilities, and pin exact versions so nothing changes underneath a live system without us knowing.
Changes reach the live system through the same automated, repeatable steps every time, after testing, and can be rolled back quickly if something isn't right.
Assurance: knowing, not hoping
The last layer runs through all the others. It's how you know the rest are working.
- Automated tests check the security rules themselves, not just the features: that a customer really can't open someone else's order, and that a member of staff without the right role really is refused.
- Audit logs record who changed what and when, which matters as much for answering an everyday question as for investigating an incident.
- Monitoring. Logs and measurements from the systems we host feed into our own monitoring platform, and we watch them for our clients. Errors, unusual traffic and failed sign-ins are alerts someone sees, not lines in a file nobody reads.
- Independent testing. For systems holding particularly sensitive data, we recommend a penetration test by a specialist firm before launch and periodically after it.
Security is a process, not a feature
None of this is exotic, and that's the point. Most breaches don't come from brilliant attackers. They come from an ordinary gap that nobody was watching: an old package, a check done only in the browser, a backup that didn't restore. Layers mean one gap isn't enough, and monitoring means it doesn't stay open for long.
If you've got a security questionnaire in front of you, or you're wondering how a new system would hold up, talk to us. We'd rather have that conversation at the start.