Deploying our projects for clients who rely on us to abstract away the complexity of running websites meant that we had to take web security and cyber security seriously. There were a few basic concepts and tricks that we had learned over the years that we had the opportunity to dig deep into and expand into as mature a solution as we could implement for our clients. I'm going to be a bit redundant with my technical language and terminology because I also want my clients to read this.
The Threat Model
Public APIs/Publically Queryable Endpoints are rarely threatened by just one thing. They usually face a mix of:
- brute-force abuse
- bot-driven account actions on the websites/apps
- injection attempts (trojan-horsing self-executing code into important areas)
- cross-site request forgery on browser clients (middle-man attacks to submit false or harmful data)
- generalized endpoint hammering (recruiting botnets or maliciously overwhelming websites with millions of calls to raise billing costs or worse)
That is why one control is never enough. We assume every individual layer can fail.
Layer 1: Edge or Gateway Controls
The first layer should absorb the most mechanical abuse:
- coarse rate limiting
- challenge rules
- TLS enforcement
- request filtering before the application executes
What is the first layer? Amateur developers will expose their databases, their backend endpoints, and supposedly business-only endpoints to the public without any safeguards. That could be the first layer. Slightly more learned developers can properly design even the simplest websites to expose only what is harmless, or even create just a single entry point (you could call it "origin shielding") by leveraging reverse proxies or tunnels. This ensures that the most obvious junk and bot crawlers are rejected and prevents waste further downstream.
Sazokashi team has dealt with issues like this directly. We've had previous clients come to us complaining that their customer relationship management services were being spammed with junk leads and junk sign-ups, and not only were these bot-based actions scheduling bad, time-wasting meetings, but also clogging their database with unnecessary data.
When you publish a website to the public and start to receive traffic that is consistent and undesired, developers who are knowledgeable in these network-based solutions are the difference between vibe-coded or self-started websites.
Layer 2: Reverse Proxy Controls
A second layer at the proxy or ingress tier adds useful redundancy.
It can:
- apply route-specific limits
- separate write-heavy and read-heavy traffic
- enforce internal routing boundaries
- narrow which networks can reach backend services
This layer matters because a security model should not collapse if one gateway rule is bypassed or misconfigured. What is this layer about? What is reverse proxy? Reverse proxy essentially a software program whose job is to sit between the public internet and your website's (the "origin server"). Built into the reverse proxy are specific rules and protocols that it will follow as the public, bots, malicious actors try to "query" or make a call to your IP address.
At Sazokashi, we particularly love the Cloudflare reverse proxy service to provide double SSL termination. What is this? It basically forces all of the public, Cloudflare itself, as your website's servers to communicate explicitly via HTTPS, thus ensuring end-to-end encryption (Full Strict SSL). This ensures privacy and authentication when sending and receiving data. This greatly reduces the range and ability of bad actors to perform common attacks. It's also a great sign to security minded consumers that they can trust your business.
Layer 3: Application-Level Limiters
The application still needs its own practical toolset for dealing with abuse.
That is where you typically want:
- per-endpoint limiters
- per-user or per-IP counters
- category-specific thresholds
- shared counters across instances via an external store
Application-level rate limiting provides the finest control because the app understands intent, not just path patterns. For example, We know of some competitor websites who implemented their website with Supabase and React.js. It sounds modern, it sounds decent. They left their public Supabase key viewable in the Developer Tools (that's not too bad, it's designed that way..), they left all of their API endpoints exposed to the public (I could literally query their database and print out their users, financial records, media assets, the URLs of their paid content on the hosting solutions). To make matters worse, I could tell that they didn't possess any concept of rate-limiting or DoS attacks or the implications it would have on their bill per call services with Vercel and Supabase. A malicious actor could literally set up a simple VM with VPN, an even simpler curl bash script on a for loop and hammer their endpoints for a few hours and then ephemerally spin the VM down. Their small business would be crumbled. That's what attacks can look like. We did the right thing and we reached out to them personally and gave them a small warning. Our client's don't need to worry about stuff like this (Hopefully. Let's be honest. There is always someone smarter who could attempt exploitation. Let's hope they're good people.)
Request Sanitization AND Validation
Input sanitization and validation is still necessary even in strongly typed applications.
For document databases, operator injection is a classic example. If user-controlled objects are allowed to carry query operators, application assumptions collapse quickly.
The fix is not complicated:
- validate structure
- strip dangerous keys
- recurse into nested objects when needed
- constrain string length and allowed content
Security here comes from boring consistency, not cleverness. This is low level fruit when designing API endpoints. It's not glamourous work, but it is necessary and a hallmark of a team that just cares.
Browser Security Controls
If a browser client authenticates with cookies, the application must defend the browser-specific attack surface.
That includes:
- strict security headers
- clickjacking protection
- transport enforcement
- CSRF protection for state-changing routes
CSRF tokens should be compared using timing-safe logic. Otherwise the token check itself can leak information.
Bot Controls on Sensitive Endpoints
Some routes deserve challenge-based bot friction:
- account creation
- password reset
- credential recovery
- other abuse-prone write endpoints
These controls are most effective when combined with rate limiting rather than treated as a substitute for it.
Network Isolation
Security posture improves dramatically when data services are not exposed on the same surface as application services.
A healthy baseline is:
- backend reachable only through an internal gateway or controlled network path
- database not publicly exposed
- cache not publicly exposed
This reduces the blast radius if an application service is compromised.
Logging Without Leaking
Good observability often turns into accidental data disclosure if logs are not treated carefully.
Sensitive material should never be written to logs:
- credentials
- token values
- connection strings
- personal data that is not operationally necessary
Structured logging is most useful when it provides traceability without turning your log pipeline into a secondary secrets store.
Design Lessons
- Edge filtering, proxy controls, and app limiters solve different problems.
- Sanitization is still essential even in typed codebases.
- Browser authentication requires browser-specific defenses.
- Sensitive account flows deserve challenge-based friction.
- Security logging should maximize diagnosis while minimizing data exposure.