What Two Years Without Architecture Oversight Cost a Healthcare Company
A European online prescription company operated two years without architecture review on its Laravel admin platform. When a reactivation audit ran in early 2026, it found three critical failures: server disk at 10 to 15 days of remaining capacity, 30,000 unencrypted patient records reachable through a public unauthenticated API endpoint, and zero backup configuration since the system went live. GDPR exposure was calculable at EUR 20 million.
Background
The Context: Two Years Without a Second Set of Eyes
The original engagement was a defined project: three WordPress and Elementor sites for a European online prescription company. A primary brand site, a secondary treatment-specific site, and a pharmacy-facing subdomain, built for a regulated healthcare niche where broken forms mean patients missing medication and incorrect treatment content creates regulatory exposure.
The sites were handed over in good structural condition. The founder moved on to the next growth phase. The clinical volume was increasing, and managing prescriptions through WordPress plugins was not a viable path at scale. A separate development team, unrelated to the original build, was hired to create a custom Laravel admin panel. The right tool for what the business was becoming.
That team built the Laravel system, delivered it, and it appeared to function. Prescriptions processed. Patient records stored. Pharmacy integrations completed. The admin panel returned correct results.
What no one reviewed during those two years was the layer underneath.
This is how invisible technical debt accumulates. Development without ongoing architecture oversight produces shortcuts that do not break things immediately. Unrotated logs fill slowly. Unauthenticated endpoints stay silent until they are discovered. The admin panel kept processing prescriptions. The infrastructure was degrading the entire time.
Discovery
What the Audit Found
A reactivation message in early 2026 started with a genuine question: how are things going? The response was immediate: the admin panel was behaving strangely. That presenting symptom turned out to be the visible edge of a much larger set of failures.
Within 48 hours of server access, four findings were documented:
Disk with 10 to 15 Days of Remaining Capacity
The production server had never had log rotation configured. Every request, database query, PHP error, and access log had been writing to flat files since the server was provisioned. Nothing had ever cleared it. At the current growth rate, the disk had between 10 and 15 days before it filled. When a production database server disk reaches capacity, MySQL cannot commit transactions. Without any backup system, the result is data corruption with no recovery path.
30,000 Patient Records Stored Without Encryption
MySQL held over 30,000 patient records: full names, home addresses, phone numbers, documented medical conditions, specific medications prescribed, prescription histories, and payment data. All stored as plaintext. No field-level encryption on sensitive columns. No tokenization for payment information. GDPR Article 9 classifies health data as special category data carrying the highest tier of regulatory protection. Appropriate technical safeguards, in this context, means encryption. It is a legal requirement, not a recommended practice.
Unauthenticated Public API Endpoint
The patient database was accessible through an endpoint that required no authentication. No token, no API key, no authentication header, no session validation. The endpoint was reachable from the public internet and returned patient records in response to queries from any source.
DDoS Attack Confirming Prior Discovery
After the endpoint was identified and closed, a distributed denial-of-service attack began. The timing is the signal. An attack that follows the closure of an unauthenticated data endpoint is the response to losing access. The data had very likely already been harvested before the audit began. The question was no longer whether an exposure had occurred. The question was what had been done with it.
GDPR exposure for 30,000 special-category health records, stored without encryption, accessible through a public endpoint, with no breach notification process and no data protection officer on record: fines reach EUR 20 million or 4% of annual global turnover, whichever is higher.
The six-day window between reconnection and disk failure was not wide. Had the audit happened three weeks later, the database would have been gone.
Response
Emergency Stabilization: Making the System Safe to Build On
The first week had one goal: keep the system alive long enough to fix it. Not improvements. Continuity.
Emergency server migration moved the failing environment to a stable host with adequate disk capacity. Backups were configured and ran for the first time in the platform's operational history. The unauthenticated API endpoint was closed and authentication was added. DDoS mitigation was put in place. Log rotation was configured.
The server had a future. That was week one.
Structural repair followed in the weeks after. Laravel was updated. PHP was updated. MySQL was brought to a supported release. The codebase was refactored: dead code removed, authentication patterns standardized, query structures reviewed and corrected where raw interpolation had been used.
The WordPress sites, originally built for this client, had fared better through two years of neglect. The custom Elementor widgets were still functional. A Core Web Vitals issue traced to 42 render-blocking CSS files was producing a Cumulative Layout Shift score between 0.8 and 1.0. A Roboto font reference pointing to a defunct development server was loading on every page. Both were resolved.
A related family business website had experienced similar neglect. It was taken on as part of the same engagement, audited, and brought to stable working state.
Stabilization is not the same as rebuild. Rebuilding from a position of crisis means making architectural decisions under time pressure with incomplete information. Stabilizing first creates the space to make those decisions properly. The three build tracks that followed were designed from clarity, not panic.
Forward Work
Three Build Tracks: The Forward Work
Track 1: Marketing Attribution Pipeline
Meta Ads was running blind. The pixel configuration was posting conversion events to the wrong ad account. The business was spending on paid acquisition with zero reliable signal about which sources produced consultations.
Data Layer
AttributionTracker.js handles 13 distinct traffic channels. Nine consent management integrations built in for EU ePrivacy compliance. Cross-subdomain attribution carries source data from first landing through consultation completion.
Pipeline
8 n8n workflows move attribution data to a Supabase warehouse (80 columns per record, 5,000+ submissions). 36 Typeform forms tracked. 3 Meta pixels managed with compliance-aware event routing. Three reporting cadences (daily, weekly, monthly) delivered as HTML emails.
What the audit uncovered
33 forms had never been connected to tracking. 14 submissions silently dropped (Typeform webhook returning 200 but not processing). 215 historical conversions recovered after pixel account correction.
This track is in production.
Track 2: Website Migration
LCP on mobile: 30.3 seconds. 732KB of inline CSS from Elementor on every page load. For a healthcare YMYL site, this is a structural ranking problem.
Target architecture
Astro monorepo, Sanity CMS, Cloudflare Pages. Static HTML at build time. A 30-second page becomes a file delivery operation.
Content audit
Playwright crawl catalogued 107 pages, 87 posts, 630 media items, 7 third-party integrations. Several integrations were undocumented, only visible through network request capture.
E-E-A-T gaps
No medical review attribution on treatment pages. No author bylines with verifiable credentials. No healthcare structured data. The migration addresses all of these.
242 hours. $9,680. Estimate went through four versions.
This track is in progress.
Track 3: Platform Rebuild
The Laravel prescription platform has a synchronous pharmacy API: 10 to 12 seconds per call. At current volume, manageable. At 10,000 prescriptions/month, an architectural bottleneck.
Rebuild scope
Multi-doctor dashboards. Patient portal. Asynchronous pharmacy API queue. GDPR-compliant field-level encryption. Regulatory audit log system.
Ten phases. $17,500. Accepted in principle.
Lessons
What the Pattern Reveals About Architecture Oversight
Three observations for founders and technical decision-makers reading this as a case study:
Architecture oversight is not an emergency measure. It is an ongoing investment in knowing what your systems actually contain. For more on what production systems require versus demos, that gap applies beyond healthcare. See also a trading system built with 655 tests under the same rigor.