1

I've built an RSVP web application with a React front end, Node.js backend, NGINX webserver, SQL database and hosted on a DigitalOcean Droplet with Ubuntu. The issue is, every time I want to launch the application with different content (i.e. different events, locations, dates, etc.), I need to manually duplicate the code, update the content, create new A names on DigitalOcean, and change the Database name. I currently have the information stored in a separate JSON file that is being read by the application, which reduces the overhead when creating a new instance of the application, but I would like to automate as much of it as possible, and even create an admin page so that others can launch a new instance, and the process isn't entirely reliant on me (and make my life easier haha). Each instance will be accessed through a subdomain for a domain I already own (i.e. instance1.example.com, instance2.example.com, etc.). I was considering modifying the application as such:

  • Dockerize the front end
    • Docker configuration will receive a path to that specific instance's source of truth
    • All other requirements, packages, dependencies will be identical as application itself is never changing, just the content being displayed (only text, no images/media, or functionality will be modified)
  • Expose an API on my server that will do the following:
    • Duplicate existing NGINX templates under sites-available and soft link it to sites-enabled
    • Run Certbot to acquire SSL certificate for new subdomain (given as part of request body)
    • Restart NGINX
    • If possible (still need to do more research), add additional DNS records to DigitalOcean domain
    • Run SQL scripts to generate new DB tables based on request body values
  • Reconfigure existing APIs to take in DB name so that multiple instances can leverage existing API
  • Build an admin page
    • Define website content and subdomain name
    • Once information is verified and submitted, new API on server will be called to trigger the creation and deployment of the new instance
  • The database server itself will be a single, non-dockerized service, with new databases (and within, tables) being instantiated dynamically
  • The Node.js server will be a single, non-dockerized service, only modified slightly to handle and reroute traffic to multiple DBs as needed

I also am not expecting any crazy amount of traffic at any given moment, realistically I am probably looking at a couple of dozen or so requests to the server every day, and that would be a very busy day.

I understand this is probably a very basic design/architecture problem, but please note that I am relatively new to software design as a whole and in the very early stages of my software development career. I understand there may be a lot of problems/inefficiencies with my approach. Please provide any feedback and detailed explanations as possible, and feel free to suggest any alternative solutions or concepts I may be missing - I'm not just looking to get this over with but build an understanding of quality software design principles that will carry me through my career.

Sal
  • 121
  • 4
  • 1
    May I ask why you create a new instance? I assume the "content" of the application is stored in a database I assume. What's so unique about the instance running the frontend? I assume the frontend will not change only the data. Your proposed solution seems very overengineered. – Bart Mar 06 '21 at 09:35
  • 1
    Currently, the content is being read in from a local JSON file, because it's a small amount of data, though you are correct about the frontend being identical aside from the content. I wanted to create new instances because of the possibility of using the same application for multiple events simultaneously, each with a unique subdomain. I wanted to avoid copying and modifying the code manually, if possible, to simplify the process moving forward. Please let me know if this was still unclear. – Sal Mar 06 '21 at 20:26

1 Answers1

2

It seems possible that the missing concept here is that of tenancy. You may be asking a specific instance of "how do I take this app I made and make it a multi-tenant app?"

https://en.wikipedia.org/wiki/Multitenancy

Is this helpful?

Jason Weber
  • 320
  • 1
  • 5
  • 1
    Thank you for your response, I was vaguely awayre of multitenenacy, though I don't understand how it works, I'll take a deeper look to see if this satisfies my needs, and update shortly. Thanks! – Sal Mar 07 '21 at 18:18
  • 1
    On the plus side, this is well-trodden design territory. Most SaaS offerings have to solve for this at some point. – Jason Weber Mar 08 '21 at 03:31
  • So I looked into it a bit, and was wondering if you could clarify if I'm misunderstanding something. In my OP, the Docker solution would classify as a "single-tenant" application, correct? Since each "tenant" had their own instance of the application? – Sal Mar 08 '21 at 07:05
  • And to make my current application multi-tenanted, would this be an appropriate approach? When the application loads, it retrieves data based on the subdomain through an API call. On any subsequent call to the backend, I pass in the current tenant ID, which will be mapped to the appropriate database on the server to perform CRUD ops on the data. This results in a single instance of the frontend calling a single instance of the backend, which works with multiple DBs? I'm not worried about loadbalancing, etc. for now due to the very small scope and traffic expected, so single instances are fine. – Sal Mar 08 '21 at 07:09
  • 1
    @Sal Yes, as currently written it seems like your containerized app is single tenant. – Jason Weber Mar 09 '21 at 16:39
  • 1
    @Sal Use of a tenant ID of some kind established via authentication is a common approach. As you suggest, this enables both shared back-end components and/or per-tenant nodes (e.g. in a database per customer scenario). if you write the logic in a stateless way you'll find it easier to scale horizontally if/when the need arises (extreme scale). – Jason Weber Mar 09 '21 at 16:49