...
...
August 25, 2026

EU Rules and Your Tech Stack: It's an Architecture Problem

A recent Hacker News post argued that EU regulations are killing micro-entrepreneurs. We disagree. The problem isn't the rules, it's brittle software architecture. Here's how to solve for compliance at the code level.

architecturecompliancegdprdevelopmentbest practicestech-stack
V
VooStack Team
August 25, 2026
9 min read
EU Rules and Your Tech Stack: It's an Architecture Problem

The dream of the solo developer shipping a world-class product from a laptop is under pressure. A recent piece making the rounds on Hacker News (at https://lectronz.com/u/lectronz/articles/how-europe-is-killing-makers-and-micro-entrepreneurs) argued that a wave of European regulations like the Digital Services Act (DSA), DAC7, and GDPR is making it impossible for small makers to survive. The compliance burden, the author says, is just too high.

They're not wrong about the burden. It's real. Where we disagree is the conclusion. These regulations aren't killing small businesses. They're killing a specific way of building software: the simple, monolithic web app that treats the entire world as a single jurisdiction. The real story here isn't about legal red tape. It's about brittle architecture. The era of bolting on compliance as an afterthought is over. If you're building software today, you need to treat compliance as a core architectural concern from day one.

At AgileStack, we've seen this firsthand. Teams that treat GDPR or sales tax as a 'last-mile' problem end up in a world of pain. They get stuck in refactoring hell, trying to disentangle user data from a single database or jam region-specific logic into a controller that was never designed for it. The teams that succeed are the ones who see this for what it is: an engineering problem that demands a robust, decoupled solution.

The Monolith Can't Handle Reality Anymore

Think about the classic SaaS starter project. Maybe it's a Rails, Django, or Node.js app. You have a user model, a subscription model, and you hook it up to Stripe. For a decade, that was enough to get you started. You could reach a global audience with a few days of work.

Now, let's map the new reality onto that simple architecture.

  1. VAT MOSS: A customer signs up from Germany. You now need to identify their location, calculate the correct Value Added Tax (19% for Germany), collect it, and remit it to the German government via the EU's One-Stop Shop. Your simple price_in_cents column in the plans table just became obsolete. You now need a dynamic pricing engine that's location-aware. Where does that logic live? In your controller? In the model? It gets messy fast.

  2. GDPR: That German customer invokes their right to be forgotten. You can't just run DELETE FROM users WHERE id = ?. What about the logs that contain their email address? What about the data in your transactional email provider (like MailStack)? Or your analytics platform? A simple delete operation has now become a complex, distributed transaction across multiple systems, all of which need to be audited.

  3. Digital Services Act (DSA): If you allow user-generated content, you now have new obligations for content moderation and transparency. This means you need systems to track reports, actions taken, and notify users. This isn't just business logic. It's a formal, auditable process that your software must enforce. Your posts table with a simple is_hidden boolean flag is no longer sufficient.

When you try to shoehorn these requirements into a classic monolith, you end up with a mess of if (user.is_eu) statements scattered across your codebase. Your business logic becomes hopelessly tangled with compliance logic. It's unmaintainable, untestable, and a huge drag on your team's velocity. This isn't a legal problem. It's a code smell.

Your Stack Needs a Compliance Abstraction Layer

The solution is to stop thinking about compliance as a feature and start thinking about it as a cross-cutting concern, like logging or authentication. You need to build an abstraction layer for it. A set of services and interfaces that isolate compliance logic from the core functionality of your application.

What does this 'compliance layer' actually do? It becomes a central clearinghouse for any operation that has regulatory implications.

Key Components of a Compliance Layer

  • Policy Engine: This is the brain. It's a service that can answer questions like, "What's the tax rate for a customer in Portugal?" or "What's the data retention policy for an inactive user in California?" This could be a simple internal microservice or a sophisticated system using a rules engine like Open Policy Agent (OPA).
  • Identity & Location Service: You can't apply policy without knowing who and where your user is. This service is responsible for securely storing user identity and reliably determining their geographic location at the time of a transaction. It abstracts away the complexity of GeoIP lookups, address verification, and identity proofs.
  • Data Residency Manager: This component knows where data is allowed to live. When your application needs to save user data, it doesn't talk directly to a database. It asks the Data Residency Manager, "Store this PII for EU user 123." The manager then routes the data to the correct physical location, maybe a Postgres instance running in eu-central-1.
  • Audit Log: Every action taken by the compliance layer must be recorded in an immutable log. When a user's data is deleted for a GDPR request, the log should record who made the request, when it was fulfilled, and which systems were affected. This isn't your standard application log. It's a permanent, verifiable record for regulators.

Building this doesn't mean you have to write everything from scratch. It's about choosing the right tools and composing them intelligently. Use a Merchant of Record like Paddle or Lemon Squeezy to completely outsource VAT MOSS. Use a dedicated service for consent management. Your job is to architect the glue that connects these services to your core application in a clean, decoupled way.

Refactoring for Compliance: A Practical Example

Let's make this concrete. Imagine we have a simple note-taking SaaS built with Node.js and Express. The 'old way' might look like this.

// The old, brittle way
app.post('/notes', async (req, res) => {
  const { userId, content } = req.body;

  // Is the user in the EU? Check their profile maybe?
  // This gets messy fast. What if their profile is out of date?
  const user = await db.users.find(userId);
  if (user.country === 'DE') {
    // Special logging for EU? Encrypt differently?
    // Compliance logic is tangled with business logic.
  }

  const note = await db.notes.create({ userId, content });
  res.json(note);
});

This is a maintenance nightmare. Every developer who touches this endpoint needs to be a compliance expert.

Now, let's refactor this to use a compliance layer. We'll introduce the concept of a complianceService that our application can call.

// Pseudocode: A better, decoupled way

// 1. A compliance middleware runs first
app.use(async (req, res, next) => {
  const userRegion = await locationService.getRegion(req.ip);
  const policy = await policyEngine.getPolicyForRequest(req.user, userRegion);
  req.compliancePolicy = policy; // Attach policy to the request object
  next();
});

// 2. The data storage logic is abstracted
class NoteRepository {
  constructor(db, auditLog) {
    this.db = db;
    this.auditLog = auditLog;
  }

  async create(note, policy) {
    // Use the policy to determine WHERE to store the data
    const databaseConnection = this.db.getConnectionForRegion(policy.dataResidency);
    
    const newNote = await databaseConnection.notes.create(note);

    // Log the action to an immutable audit trail
    await this.auditLog.log('NOTE_CREATED', { 
      noteId: newNote.id, 
      userId: note.userId, 
      region: policy.dataResidency 
    });

    return newNote;
  }
}

// 3. The controller is clean and simple again
const noteRepository = new NoteRepository(db, auditLog);

app.post('/notes', async (req, res) => {
  const { userId, content } = req.body;
  
  // The controller doesn't know or care about compliance rules.
  // It just passes the policy object to the data layer.
  const note = await noteRepository.create({ userId, content }, req.compliancePolicy);
  
  res.json(note);
});

Look at the difference. The Express route handler is back to doing one thing: handling HTTP requests. The complex logic about data residency and auditing is neatly encapsulated in the NoteRepository and the middleware. We can now change our data residency rules by updating the policyEngine without ever touching the application's core business logic. This is a resilient, scalable architecture.

This Is the Future of Global Software

It's tempting to view this as a 'Europe problem'. It's not. California has the CCPA and CPRA. Canada has PIPEDA. Brazil has the LGPD. The global trend is unambiguous: governments are enforcing digital sovereignty and user rights. The internet is no longer a lawless frontier. It's being balkanized into regulatory zones, and your software must be able to navigate them.

Building a compliance-first architecture isn't just about avoiding fines. It's a massive competitive advantage. When a new market introduces a data residency law, a team with a compliance layer can adapt in days. They update their policy engine, spin up a new database in the required region, and deploy. A team with a tangled monolith faces months of painful, risky refactoring. Who do you think will win?

This is a huge opportunity for developers, architects, and companies like us. The demand for tools and consulting (like our work at AgileStack and our products like ESig and MailStack) that simplify this complexity is exploding. Building these systems is the new frontier of web development.

What This Means for Your Team

  • Stop treating compliance as a legal problem. It's an architecture problem. Get your engineers and architects involved from the very beginning. They're the ones who have to build it.
  • Isolate compliance logic. Never let policy logic bleed into your core business logic. Use middleware, dedicated services, or an event-driven architecture to keep them separate.
  • Outsource aggressively. Don't build your own global tax collection system. Use a Merchant of Record like Paddle, Stripe Tax, or Quaderno. Their entire business is solving this one problem.
  • Design for data locality from day one. Even if you only deploy in us-east-1 today, design your data layer as if it might need to run in multiple regions tomorrow. Tag data with its origin and policy requirements.
  • Log for the audit. Your standard application logs are not enough. You need a separate, immutable audit log that tracks every compliance-related event. When the regulators come knocking, this will be your best friend.

The friction for solo developers is real, but the answer isn't to wish the regulations away. The answer is to build better, more disciplined software. The internet is growing up, and our architectures need to grow up with it.


Building something in this space? AgileStack helps teams ship enterprise-grade software without the consulting-firm overhead. Book a 30-minute call and tell us what you're working on.

Topics
architecturecompliancegdprdevelopmentbest practicestech-stack
Authored by
V

VooStack Team

Engineering, VooStack

The VooStack engineering team. A veteran-owned, SDVOSB-certified software house building Flutter, .NET, and cloud-native products end to end, from San Antonio, TX and Oklahoma City, OK.

Share this article