PHP Laravel

Hardening Critical Features: Newsletter Delivery, Rate Limits, and Multi-Tenancy in Laravel

The landing project serves as a crucial platform for content delivery and user engagement, encompassing features like scheduled newsletters and integration with AI models. Recent development efforts focused on significantly enhancing the robustness and correctness of these core services, particularly within a multi-tenant application architecture. This post details the key improvements made to ensure more reliable feature operation and better data integrity.

Refining Newsletter Scheduling and Delivery

Previously, our newsletter system faced challenges related to scheduling precision and the potential for duplicate dispatches. To address these, the scheduling logic was tightened:

  • Precise Scheduling: Newsletter job triggers now incorporate checks for both hour and minute, ensuring that scheduled content is sent at the exact intended time.
  • Sending Guard: A 7-day guard was implemented to prevent newsletters from being sent too frequently to the same audience, improving user experience and reducing potential spam flagging.
  • Deduplication on Retry: A per-subscriber tracking mechanism was introduced. This ensures that even if a newsletter job fails and retries, individual subscribers do not receive duplicate emails, maintaining delivery integrity.
  • Content Filtering: The published_at timestamp on posts is now rigorously used for digest filtering, guaranteeing that only relevant, recently published content is included in outgoing newsletters.
  • Multi-Tenant Link Handling: In a multi-tenant setup, it's critical that links within emails point to the correct tenant's specific content. The baseUrl is now explicitly passed to the mailable, ensuring all post links are correctly generated for the intended tenant.

Here's a simplified example demonstrating how published_at might be used in a Laravel model scope to filter posts for a weekly digest:

use Carbon\Carbon;

class Post extends Model
{
    protected $dates = ['published_at'];

    public function scopeForNewsletterDigest($query)
    {
        return $query->whereNotNull('published_at')
                     ->where('published_at', '<=', Carbon::now())
                     ->where('published_at', '>=', Carbon::now()->subDays(7));
    }
}

// In a newsletter job or service:
$postsForDigest = Post::forNewsletterDigest()->get();

This scope efficiently retrieves posts that have been published within the last seven days and are ready for inclusion in a digest.

Bolstering Multi-Tenant Database Interactions

Ensuring correct data isolation and access in a multi-tenant application is paramount. For database systems like PostgreSQL, which often use schema-based multi-tenancy, precise schema identification is key. A fix was implemented to consistently quote schema identifiers in all SET search_path statements. This prevents potential issues with database schema resolution, especially when identifiers contain special characters or keywords, thus reinforcing the integrity of tenant-specific data access.

Improving AI Feature Rate Limiting

Our integration with AI models includes rate limiting to manage API usage and prevent abuse. Two crucial improvements were made in this area:

  • Data Type Correction: The database column storing rate limits was changed from ->numeric() to ->integer(). This provides a more accurate and efficient storage for count-based rate limits, avoiding floating-point precision issues where whole numbers are expected.
  • Carbon Mutation Bug Fix: A subtle bug was identified and resolved in the AiRateLimitService where Carbon date objects were being unintentionally mutated during rate limit checks. The fix ensures that the service accurately determines if a rate limit has been exceeded without side effects, returning 0 when no limit is active or exceeded.

The Lesson

Developing robust, scalable applications requires meticulous attention to detail, especially in critical paths like scheduled jobs, multi-tenancy, and third-party integrations. Defensive programming, careful data type selection, and explicit handling of environmental contexts (like baseUrl for multi-tenant links) are not just good practices—they are essential for delivering reliable and maintainable software. These recent updates underscore the ongoing commitment to building a resilient and precise platform.

Hardening Critical Features: Newsletter Delivery, Rate Limits, and Multi-Tenancy in Laravel
GERARDO RUIZ

GERARDO RUIZ

Author

Share: