
How we use IP geolocation for security alerts, fraud detection, and geographic rate limiting, and our approach to AI-powered content moderation — balancing safety with free expression across a global platform.
A platform that serves 89 countries needs to know where its users are — not to track them, but to protect them. When someone logs in from a new country, we need to flag it. When a suspicious IP hammers an API endpoint, we need to throttle it based on where it is coming from. And when users post content on a social platform, we need to catch toxicity before it reaches other people's feeds. This article covers two utilities from tctf-utils that handle these concerns: the GeoLocation service for IP-based location intelligence, and the Content Moderation service for AI-powered toxicity detection.
Every API request to the TCTF platform arrives with an IP address. That IP address tells us something valuable — where the request is coming from. Not with GPS precision, but with enough accuracy to answer the questions that matter for security.
Is this login from a country the user has never logged in from before? That is a security alert. Is this IP address associated with a known VPN or proxy service? That is a risk signal. Is a burst of requests coming from a region where we have no users? That might be an attack.
Geolocation is not about surveillance. We do not track user movements or build location profiles. We use IP geolocation at the moment of the request to make security decisions — and then we discard the raw IP. The location data we store is country-level, not street-level. It is enough to detect anomalies without invading privacy.
The GeoLocation service in tctf-utils is the shared utility that every service uses for this. Authentication uses it for login anomaly detection. Rate limiting uses it for geographic throttling rules. The activity service uses it for security alert notifications. One service, one API, consistent behavior across all 34 microservices.
🔒Geolocation is not surveillance. We use IP location at the moment of the request to make security decisions — country-level, not street-level. Enough to detect anomalies without invading privacy.

The GeoLocation service is built as a singleton with lazy initialization. When a service needs to look up an IP address, it calls GeoLocationService.getInstance() and then getLocation(ip). The service handles everything else — API calls, caching, rate limiting, circuit breaking, and error handling.
Under the hood, the service calls the ipinfo.io API to resolve an IP address to a country, region, city, timezone, and ISP. The API key is stored in AWS Secrets Manager and resolved at runtime — never hardcoded, never in environment variables.
To avoid hammering the external API, the service implements a two-layer cache. The first layer is Redis (ElastiCache) for sub-millisecond lookups on hot IPs. The second layer is DynamoDB for persistent storage with TTL-based expiration. A cache warmup phase pre-loads frequently seen IPs on cold start.
The circuit breaker protects against ipinfo.io outages. If the external API fails repeatedly, the circuit opens and the service returns cached data or a graceful degradation response instead of failing the entire request. The circuit breaker state is managed in DynamoDB so it persists across Lambda invocations.
Rate limiting prevents abuse of the geolocation API itself — both from internal services making too many calls and from external IPs that trigger excessive lookups. The rate limiter integrates with the geographic rules manager, so throttling thresholds can vary by country.
⚡Two-layer cache (Redis + DynamoDB), circuit breaker for API outages, rate limiting, and Secrets Manager for API keys. The GeoLocation service is built for production resilience.
One of the most powerful features of the geolocation integration is geographic rate limiting. Different regions have different traffic patterns, different risk profiles, and different legitimate usage levels.
The rate limiting service accepts a geoLocation parameter on every check. This country code — extracted from the CloudFront-Viewer-Country header or resolved via the GeoLocation service — feeds into the geographic rules manager. Rules can be defined per country, per region, or per action.
For example, a country with a high volume of bot traffic might get stricter rate limits on authentication endpoints. A region with no registered users might get aggressive throttling on signup attempts. A country where the platform has a large user base gets more generous limits.
The geographic rules are stored in DynamoDB and can be updated without redeploying any service. This means the security team can respond to emerging threats by adjusting geographic rules in real time — no code changes, no deployments, no downtime.
The tier-based rate limiting service extends this further. A premium user in any country gets higher limits than a free user. But a free user in a high-risk region might get lower limits than a free user in a low-risk region. The combination of user tier and geographic context creates a nuanced, adaptive throttling system.
A social platform where people post, comment, and message each other needs content moderation. Without it, the platform becomes a vector for hate speech, harassment, spam, and abuse. With too much of it, the platform becomes a place where people feel censored and unwelcome.
The challenge is balance. We want to catch genuinely toxic content — hate speech, threats of violence, sexual content, and targeted harassment — while allowing vigorous debate, strong opinions, and the kind of direct communication that tech communities value.
This is especially complex on a multilingual platform. Toxicity detection that works well in English may miss nuances in Yoruba or produce false positives in French. Cultural context matters — a phrase that is offensive in one culture may be perfectly normal in another.
Our approach: use AI as the first line of defense, with human review as the backstop. Automated moderation catches the obvious cases. Borderline cases get flagged for human review. And the system learns from every decision.
⚖️The challenge is balance. Catch genuinely toxic content while allowing vigorous debate and strong opinions. AI catches the obvious cases. Humans handle the borderline ones.
The content moderation service uses AWS Comprehend's toxicity detection as its primary engine. When content is submitted — a post, a comment, a message, a project description — the moderateContent function sends the text to Comprehend and receives a toxicity analysis across five categories: hate speech, violence or threats, sexual content, profanity, and insults or demeaning language.
Each category returns a confidence score between 0 and 1. The service aggregates these scores into an overall toxicity score. Content below 0.5 is considered appropriate. Content above 0.5 triggers a suggested action: flag for review, auto-hide, or block.
The service supports batch moderation through moderateContentBatch, which processes multiple texts in parallel. This is used when a user submits a post with multiple comments, or when the activity service processes a batch of notifications.
When AWS Comprehend is unavailable — network issues, service outages, or rate limiting — the service falls back to keyword-based filtering. The fallback is deliberately conservative: it catches obvious profanity and known toxic patterns, but it does not attempt the nuanced analysis that Comprehend provides. The fallback keeps the platform safe during outages without over-blocking legitimate content.
Every moderation decision is logged with a correlation ID, the confidence score, the suggested action, and the categories that triggered. This audit trail is essential for reviewing decisions, training the system, and responding to user appeals.
🛡️ AWS Comprehend detects toxicity across 5 categories. Keyword-based fallback keeps the platform safe during outages. Every decision is logged with a correlation ID for audit and appeals.
Content moderation catches toxic meaning. Input sanitization catches toxic code. The security module in tctf-utils provides a comprehensive sanitization layer that runs before content ever reaches the moderation service.
The sanitizeInput function strips control characters, limits string length, and removes potentially dangerous patterns. The sanitizeHtml function removes HTML tags to prevent cross-site scripting. The sanitizeObject function recursively sanitizes all string properties in a request body.
Specialized sanitizers handle specific contexts: sanitizeUrl validates and cleans URLs, sanitizePath prevents directory traversal attacks, sanitizeJson handles JSON injection, and sanitizeRegex escapes special characters for safe regex construction. Even phone numbers get their own sanitizer.
The key principle: sanitize at the boundary. Every piece of user input is sanitized the moment it enters the system — before it touches business logic, before it reaches the database, before it is rendered in any response. This defense-in-depth approach means that even if one layer fails, the others catch the problem.
Sanitization and moderation work together. Sanitization ensures the input is safe to process. Moderation ensures the content is appropriate to display. Together, they protect both the platform infrastructure and the user community.
Not everyone can moderate content. The RBAC system in tctf-utils defines specific moderation permissions: content:moderate for reviewing and acting on flagged content, and users:moderate for managing user accounts that violate community guidelines.
These permissions are assigned to moderator and admin roles. Regular users can report content, but they cannot see the moderation queue, override moderation decisions, or access the audit logs. This separation ensures that moderation power is controlled and accountable.
The moderation workflow integrates with the activity service. When content is flagged, the author receives a notification explaining what happened and how to appeal. When a moderator takes action, the decision is logged and the author is notified of the outcome. Transparency is not optional — it is how we build trust with the community.
As the platform grows and supports more languages, the moderation system will need to evolve. Community moderators who speak the platform's supported languages will be essential for handling content that AI cannot reliably assess. The achievement system already recognizes moderation contributions — moderators earn progression for their work, just like developers earn progression for code contributions.
👥Moderation is controlled by RBAC permissions. Every decision is logged. Authors are notified and can appeal. Transparency builds trust.

Geolocation and content moderation are not glamorous features. Nobody signs up for a platform because of its IP lookup cache or its toxicity detection pipeline. But they are the features that make a platform trustworthy. They protect users from fraud, abuse, and harassment. They enable geographic intelligence that makes rate limiting smarter and security alerts more accurate. And they do it all behind the scenes, without the user ever knowing. That is the point — trust infrastructure should be invisible when it works and unmistakable when it matters.
Never miss an edition
Subscribe to get TCTF newsletters delivered to your inbox.