# How to use microfrontend in a multitenant instance

**URL:** <https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936>\
**Category:** Frontend\
**Tags:** how-to, mfe\
**Created:** [March 30, 2022, 11:05pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936 "2022-03-30T23:05:59Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![dcoa](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/dcoa/32/3246_2.png) [@dcoa](https://discuss.openedx.org/u/dcoa)\
**Post date:** [March 30, 2022, 11:05pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/1 "2022-03-30T23:05:59Z")

</div>

Hi all,

We start thinking about how to use the micro-frontend in a multitenancy installation, we want to share with you our first iteration, get feedback and find a way to make a solution for the community.

**The proposal**

Frontend-platform recommended extending the initialization handler for [config runtime](https://openedx.github.io/frontend-platform/module-Config.html), with that in mind, we think to get the site configuration values through a REST API with a new handler (don’t touch config handler to maintain env config and the actual workflow, where each MFE could override it, for example, in [account](https://github.com/openedx/frontend-app-account/blob/97164959515477ebc95399d031129be1e633b8ce/src/index.jsx#L59)).

In this case, we don’t have to modify the base code on each MFE.

**Test Environment**  
This proposal was tested in a Tutor Maple dev installation with these plugins:

1. [tutor-mfe](https://github.com/overhangio/tutor-mfe/tree/64bcc830b6d11923201ea819e4ed5abd2a712246) : _" easily add micro frontend (MFE) applications on top of an Open edX platform that runs with Tutor"_

2. [eox-tenant](https://github.com/eduNEXT/eox-tenant) " _a multi-tenancy Django app for edx-platform"_

In addition, we use a mock API ([http://localhost:3000/config/tenant\_id](http://localhost:3000/config/tenant_id)) with some config information, which “common” is a config for all MFE

```json
{
     {
      "id": "tenant-a.lms.mango.edunext.link",
      "common": {
        "SITE_NAME": "Tenant A",
        "LOGO_URL": "https://www.example.com/tiger.png",
        "LOGO_TRADEMARK_URL": "https://www.example.com/tiger.png",
        "LOGO_WHITE_URL": "https://www.example.com/tiger.png",
        "FAVICON_URL": "https://www.example.com/tiger.png",
        "LEARNING_BASE_URL": "http://tenant-a.lms.mango.edunext.link:2000",
        "LMS_BASE_URL": "http://tenant-a.lms.mango.edunext.link:8000",
        "LOGIN_URL": "http://tenant-a.lms.mango.edunext.link:8000/login",
        "LOGOUT_URL": "http://tenant-a.lms.mango.edunext.link:8000/logout"
      }
    },
    {
      "id": "tenant-b.lms.mango.edunext.link",
      "common": {
        "SITE_NAME": "Tenant B",
        "LOGO_URL": "https://www.example.com/cat.png",
        "LOGO_TRADEMARK_URL": "https://www.example.com/cat.png",
        "LOGO_WHITE_URL": "https://www.example.com/cat.png",
        "FAVICON_URL": "https://www.example.com/cat.png",
        "LEARNING_BASE_URL": "http://tenant-b.lms.mango.edunext.link:2000",
        "LMS_BASE_URL": "http://tenant-b.lms.mango.edunext.link:8000",
        "LOGIN_URL": "http://tenant-b.lms.mango.edunext.link:8000/login",
        "LOGOUT_URL": "http://tenant-b.lms.mango.edunext.link:8000/logout"
      },
// example add optional variables or specific for a MFE
      "auth": {
        "INFO_EMAIL": "diana.olarte@edunext.co"
      }
}

```

**Steps to follow**

_In frontend-platform_

We fork frontend-platform for testing purposes and make some modifications (you can look it out below), following the next steps:

- Create a new config variable to know if is a multitenant instance or not; this could be set in the env settings (like default config).

```auto
 MULTITENANT_API: true

```

- Create a function (getHttpConfig) to call the API with the config. We think it’s a good idea to use the [cache system](https://github.com/openedx/frontend-platform/blob/master/docs/how_tos/caching.rst).

- Create a handler for the initialize method (we call that configTenant).

- Add validation in the initialize to call one of the handlers: config or configTenant.

_**You can check the first version of the code [here](https://github.com/eduNEXT/frontend-platform/commit/7982dc983e9caffaa149eec9fa812176af594c52)**_ (we’re happy to get feedback 🙂 )

_Note_: We use[module.config.js](https://github.com/openedx/frontend-build#local-module-configuration-for-webpack) to develop these changes and test frontend-platform.

_In the tenant config of Django Admin_

We found out it’s possible to config the URL through the tenant settings like this:

```json
{
    "ACCOUNT_MICROFRONTEND_URL": "http://tenant-b.lms.mango.edunext.link:1997/account",
    "ENABLE_PROFILE_MICROFRONTEND": true,
    "LEARNING_MICROFRONTEND_URL": "http://tenant-b.lms.mango.edunext.link:2000/learning",
    "LMS_BASE": "tenant-b.lms.mango.edunext.link:8000",
    "LMS_ROOT_URL": "http://tenant-b.lms.mango.edunext.link:8000",
    "PLATFORM_NAME": "Tenant B",
    "PROFILE_MICROFRONTEND_URL": "http://tenant-b.lms.mango.edunext.link:1995/profile/u/",
    "SITE_NAME": "Tenant B",
}

```

That’s why we can use the hostname to identify the tenant and the MFE (place in the path URL) to set the specific additional configuration in needed cases.

_Finally_

Use a mock API with the config of the tenant you want to test (like we explained in the test environment section), change the URL in getHttpConfig to match with your API, and test it!.

**The result**  
We want to share a screenshot of 2 tenants (the result of our test), with different values gotten by an API (mock) in the same MFE:

- The URL
- Logo and favicon
- Site name

_Tenant A_

 ![Tenant A](https://us1.discourse-cdn.com/flex020/uploads/openedx/original/2X/9/9c53c56956c598ed8089ff9cc7892b5499b11321.png)

_Tenant B_

 ![Tenant B](https://us1.discourse-cdn.com/flex020/uploads/openedx/original/2X/4/471a5e2ff0a064a0937e0672c0b70ff1539b2acd.png)

---

<div class="post-metadata">

**Author:** ![sarina](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/sarina/32/2308_2.png) [@sarina](https://discuss.openedx.org/u/sarina)\
**Post date:** [March 31, 2022, 1:47pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/2 "2022-03-31T13:47:55Z")

</div>

Hi @dcoa and welcome to the forums!! 😁

I don’t have any feedback specifically but I want to celebrate this work. 🎉 thanks for the submission!

---

<div class="post-metadata">

**Author:** ![jboo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/jboo/32/3458_2.png) [@jboo](https://discuss.openedx.org/u/jboo)\
**Post date:** [March 31, 2022, 5:31pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/3 "2022-03-31T17:31:55Z")

</div>

Hi @dcoa:

Thanks for sharing your proposal. We recently updated to Maple version through tutor and we have doubts if this version is compatible with multi-site configurations.

I’m reviewing your post and it confirms my doubts that microfrontends does not support multi-site out-of-the-box. I think this is a big drawback and it should have been considered before put microfrontends as default option.

In the tutor [discussion](https://discuss.overhang.io/t/multi-site-tenant-support/247) @regis says that tutor does not support multi-sites and we are [wondering](https://discuss.overhang.io/t/multi-site-multi-tenancy/2613) if it is a restriction or a suggestion.

We are planning to addressing diferents sites through k8s namespaces by deploying one platform per site but before to do this, we can give a chance to implement it in a single namespace.

We have some questions regarding to your proposal:

- It is necessary the plugin eox-tenant?
- How can be synchronized the sites created dynamically through sites django admin vs the statically created response in the mock API?

Thanks

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [April 4, 2022, 12:20pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/4 "2022-04-04T12:20:40Z")

</div>

Hi Diana!

I see you tested using different subdomains (tenant-a and tenant-b) within the same lms domain (lms.mango.edunext.link). I wonder if it will work using completely different domains for each tenant (of course all CNAMEs pointing to the same LMS url) as can be done with site configurations. I doubt if caddy can support several domain names for the same site. Did you test it?

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [April 4, 2022, 12:22pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/5 "2022-04-04T12:22:35Z")

</div>

I fully agree with @jboo that multitenancy should be given a chance. There is a huge market of low-end educators that cannot afford the cost of a full implementation, even in very optimized installations as can be done with Kubernetes.

---

<div class="post-metadata">

**Author:** ![jboo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/jboo/32/3458_2.png) [@jboo](https://discuss.openedx.org/u/jboo)\
**Post date:** [April 5, 2022, 6:35am UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/6 "2022-04-05T06:35:23Z")

</div>

Hello @dcoa

I think the biggest drawback to getting it works is in how the microfrontend url is obtained in the backend.

For example, in the case of learning microfrontend, reviewing the code of the platform I see this in [url\_helpers.py](https://github.com/openedx/edx-platform/blob/master/openedx/features/course_experience/url_helpers.py):

- `mfe_link = f'{settings.LEARNING_MICROFRONTEND_URL}/course/{course_key}'`

The LEARNING\_MICROFRONTEND\_URL value is not being retrieved through the site configuration by using the [site configuration helpers](https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/site_configuration/helpers.py#L119), as it is being done in other points of the platform to obtain other values from the settings.

How did you address this in your proposal?

Thanks.

---

<div class="post-metadata">

**Author:** ![dcoa](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/dcoa/32/3246_2.png) [@dcoa](https://discuss.openedx.org/u/dcoa)\
**Post date:** [April 5, 2022, 3:38pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/7 "2022-04-05T15:38:16Z")

</div>

Hi @jboo and @Andres.Aulasneo, thank you for your interest in this topic.

Answering your questions:

> [@jboo](#):
>
> It is necessary the plugin eox-tenant?

Yes, this is a complex question, I understand Tutor does not recommend multitenancy but is possible to extend it with a plugin to achieve that, and this is one of the proposes of eox-tenant, and we don’t know if exists another alternative.

> [@jboo](#):
>
> How can be synchronized the sites created dynamically through sites django admin vs the statically created response in the mock API?

The main idea is that the endpoint connects with a service that can read the settings and that have to be used for the MFE.

> [@Andres.Aulasneo](#):
>
> I see you tested using different subdomains (tenant-a and tenant-b) within the same lms domain (lms.mango.edunext.link). I wonder if it will work using completely different domains for each tenant (of course all CNAMEs pointing to the same LMS url) as can be done with site configurations. I doubt if caddy can support several domain names for the same site. Did you test it?

No, it is not tested yet, but we are working on testing that.

> [@jboo](#):
>
> How did you address this in your proposal?

I’m not sure but we are setting the URL with the settings and apparently works for [tutor-mfe](https://github.com/overhangio/tutor-mfe/blob/master/tutormfe/templates/mfe/hooks/lms/init)

---

<div class="post-metadata">

**Author:** ![jboo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/jboo/32/3458_2.png) [@jboo](https://discuss.openedx.org/u/jboo)\
**Post date:** [April 6, 2022, 6:22am UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/8 "2022-04-06T06:22:15Z")

</div>

Hello,

I have opened a [PR](https://github.com/openedx/edx-platform/pull/30186) to edx-platform repository to get microfrontend URLs from site configuration. With these changes we can manage different MFE through multisites at the backend.

Still pending how to handle multiple backends from the microfrontend side. @dcoa I have linked your proposal for frontend-platform configuration.

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [April 6, 2022, 4:28pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/9 "2022-04-06T16:28:39Z")

</div>

Hi @jboo,  
I liked your PR! Did you test it?

---

<div class="post-metadata">

**Author:** ![Alecar](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/alecar/32/729_2.png) [@Alecar](https://discuss.openedx.org/u/Alecar)\
**Post date:** [April 6, 2022, 11:42pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/10 "2022-04-06T23:42:07Z")

</div>

Hi @jboo

We are setting LEARNING\_MICROFRONTEND\_URL on each “tenant config” to override the settings because currently doesn’t exist one option to override it from site configurations.

I like your PR, It might be a good solution for set it from site configurations.

---

<div class="post-metadata">

**Author:** ![Alecar](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/alecar/32/729_2.png) [@Alecar](https://discuss.openedx.org/u/Alecar)\
**Post date:** [April 6, 2022, 11:55pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/11 "2022-04-06T23:55:10Z")

</div>

Hi @Andres.Aulasneo

We were testing it and finally, we find that this is working with any sub-domain, but it depends on setting SESSION\_COOKIE\_DOMAIN.

Currently, Tutor defines it using the same LMS\_HOST on this case “lms.mango.edunext.link”.

Maybe We can do it works with a different domain but as you said, we will need some change in caddy, or maybe changing the cookies settings might be enough, We’ll work on it.

---

<div class="post-metadata">

**Author:** ![jboo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/jboo/32/3458_2.png) [@jboo](https://discuss.openedx.org/u/jboo)\
**Post date:** [April 7, 2022, 8:19am UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/12 "2022-04-07T08:19:09Z")

</div>

@Andres.Aulasneo @Alecar thanks for your likes 😉

@Alecar as you say, you have to configure SESSION\_COOKIE\_DOMAIN in site values, overwriting the default value and assigning the same value as site domain’s name, but I think this is not due to the changes introduced in the PR.

Regarding to the frontend part, we are planning to address this part by deploying as many copies of MFEs as sites, each one properly configured to the corresponding domain. Since we host MFEs in S3 it will not add an extra cost in infrastructure, but it does force us to do a new deployment every time we create a site. @dcoa with your proposal we can avoid this drawback, how did you plan to implement this part?

---

<div class="post-metadata">

**Author:** ![Andres.Aulasneo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/andres.aulasneo/32/984_2.png) [@Andres.Aulasneo](https://discuss.openedx.org/u/Andres.Aulasneo)\
**Post date:** [April 7, 2022, 9:01am UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/13 "2022-04-07T09:01:08Z")

</div>

> [@jboo](#):
>
> Regarding to the frontend part, we are planning to address this part by deploying as many copies of MFEs as sites, each one properly configured to the corresponding domain.

Anyway, I think it’s not a bad idea, despite the fact of making a new deployment for each tenant. This approach will allow to make a customized MFE for each one.

---

<div class="post-metadata">

**Author:** ![Felipe](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/felipe/32/60_2.png) [@Felipe](https://discuss.openedx.org/u/Felipe)\
**Post date:** [May 13, 2022, 12:41pm UTC](https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/14 "2022-05-13T12:41:35Z")

</div>

There was some talk about this very topic in the BTR WG during the conference and we took this a compromise to deliver some of this work soon.

I made a summarizing document at: [MFE Runtime Configuration - Google Docs](https://docs.google.com/document/d/1-FHIQmyeQZu3311x8eYUNMru4JX7Yb3UlqjmJxvM8do/edit#)

Please take a look, comment and let me know what needs changing or more discussion or if you are happy with the approach.
