Overview¶
MetaboLights WS3 is designed to address the latest goals and requirements of MetaboLights.
Separation of Concerns: Each concern (presentation, business logic, and data access) should be clearly separated. Specifically, the business logic should remain independent of the details of data storage and management.Maintainability: The architecture must support long-term maintainability. This requires clearly defined layers that adhere to the principle of separation of concerns, avoiding framework-dependent or tightly coupled (“spaghetti”) code. Layer structures and their dependencies should be automatically validated to ensure architectural integrity.Framework Independence: The business logic layer must remain independent of external frameworks. This promotes flexibility, allowing frameworks to be upgraded or substituted with minimal impact on the rest of the system. In MetaboLights, reliance on specific frameworks and external services has historically led to major issues during application and infrastructure upgrades.Testability: The architecture should allow application configurations to be easily modified and support the execution of unit, integration, functional, and non-functional tests.Extensible: The architecture should be extensible, allowing new components or frameworks to be added with minimal effort.Flexible: The architecture should support the definition and execution of multiple application types—such as REST API servers and command-line interfaces—within a single codebase or repository.Scalable: Each application should operate as a stateless service that can be easily deployed within a containerized infrastructure.
Inspiration
MetaboLights WS3 is inspired from the following software principals, architectures and approaches:
- SOLID (Single-responsibility, Open-closed Principle, Liskov substitution, Interface segregation, Dependency inversion) Object Oriented Design Principles.
- Domain Driven Design (DDD)
- Command Query Responsibility Segregation (CQRS)
- Clean Architecture
- Onion Architecture
- Hexagonal / Port & Adaptor Architecture
MetaboLights WS3 Architecture¶
The MetaboLights WS3 architecture consists of four core layers — domain, application, presentation, and infrastructure — along with an additional run layer used to customize endpoints and executables. The layers and their dependency hierarchy are illustrated below.

General design principles¶
- Each layer can use the lower layer(s) but not higher layers. For example,
infrastructurelayer can import bothapplicationanddomainlayer modules, howeverapplicationlayer can only import modules fromdomainlayer. infrastructureandpresentationlayers are on the same level and they are isolated. They do not import any modules from each other.- All external services (e.g., external web services) and python package dependencies (postgresql, redis, elasticsearch, etc.) are isolated from
applicationlayer modules. Application modules only use interfaces. Interfaces are implemented ininfrastructurelayer. For example, CacheService interface inapplicationlayer can be implemented with different frameworks (RedisCache, InMemoryCache, RedisSentinelCache, etc.) ininfrastructure. applicationlayer modules do not know how domain entities are stored and managed (on NFS, SQL or NoSQL DB, Object Storage, etc.). They use only repository interfaces to process them.- Only
presentationlayer modules will check authentication or authorization (Role based authentication and authorization). There will be no logic to check authentication or authorization inapplicationorinfrastructurelayer modules (They may access authentication and authorization information in read-only mode). - All application logic should be implemented in
applicationlayer (not inpresentationorinfrastructurelayer). presentationlayer modules should implement only RestAPI or CLI inputs and outputs (authentication and authorization). Any business logic should be moved to application and domain layer.Infrastructurelayer modules should implement only application interfaces. For example, HttpClient interface hassend_requestmethod and HttpxClient inInfrastructurelayer implements send_request method using httpx module.- Do not use any external python package dependencies in
domainorapplicationlayer (Exceptions: pydantic). dependency_injectorcontainers will be defined for each executable (ws, ws_worker, cli, etc) inrunlayer.- Prefer async coroutines for time consuming operations (external service calls, time consuming tasks etc.)
Layers and design principles¶
Domain layer¶
Domain layer contains only MetaboLights specific domain classes, enumerations, decorators, exceptions and basic utility methods.
Domainlayer imports onlycore Python packagesand the following libraries:pydanticmetabolights-utils- Basic utility libraries:
pyyaml,python-dateutil,pytz
Application layer¶
-
Applicationlayer imports onlydomainlayer packages. The only exception isdependency_injectorto define async tasks. -
All methods and classes in
applicationlayer use interfaces to access infrastructure components and services. -
Applicationlayer modules do not import any external python libraries (e.g., celery, redis, sqlachemy, etc.). Instead of importing any external library, a new service or component can be implemented ininfrastructurelayer. To implement a new service or component: -
Define interfaces in
applicationlayer. - Create any required domain objects in
domainlayer. - Implement interfaces in
infrastructurelayer. -
Update
dependency_injectorcontainer inrunlayer to use it. -
Initial interfaces in
applicationlayers are listed below: -
HttpClient AsyncTaskServiceAuthenticationService,AuthorizationServiceandIdentityServiceCacheServicePolicyService-
StudyMetadataService -
Repositories are also defined as interfaces. e.g.
Study,User,ValidationReport,ValidationOverride,StudyFile, etc. entity repositories. -
Application related logic is implemented in
use_casespackage. any module inuse_casespackage can import any other packages inapplicationlayer. -
All async tasks are implemented in
remote_taskspackage and they do not importuse_casesmodules.
You can find application layer packages and their dependency hierarchy below:

Presentation layer¶
Presentationlayer can importsapplicationanddomainlayer packages. It may also importdependency_injectorand presentation related libraries (e.g., FastAPI, click).Presentationlayer do not import anyinfrastructurelayer packages packages and modules.- Rest API, CLI or other executable can be defined as a presentation.
- Rest API endpoints are defined within API groups and each API group will be managed with versions. Initial Rest API groups are
submission,auth,curation,system, andpublic. Submission Rest API group: It provides endpoints to create and update MetaboLights submissions. Authentication is required to use endpoints.Curation Rest API group: It provides endpoints to run curation tasks on submitted studies and make them public. Authentication is required to use endpoints.Public Rest API group: It provides endpoints to access MetaboLights public studies and statistics.Auth Rest API group: It provides to endpoints to create and revoke API tokens (JWT tokens).System Rest API group: It provides to endpoints to MetaboLights sytem related endpoints (Private FTP accessibility, etc.).- Only JWT token is used to authorize requests. Each user or service that wants to access any authorized endpoints should have a valid JWT token.
- Rest API authentication will be managed within authorization middleware.
Infrastructure layer¶
Infrastructurelayer modules can importapplicationanddomainlayer modules,dependency_injectormodule and any external library (e.g., redis, slqalchemy, elasticsearch, celery, etc.).Infrastructurelayer modules do not import anypresentationlayer modules.- Multiple implementations can be defined for an interface defined in
applicationlayer. Each implementation is isolated from each others. - Initial Service and repository implementations:
- AsyncTaskService:
Celeryandthread(for development) implementations - AuthenticationService, AuthorizationService and IdentityService:
mtbls_ws2 proxyandstandaloneimplementations. - CacheService:
Redis,Redis sentinelandin-memory(for development) implementations - PolicyService: Open policy agency (
OPA) implementation - StudyMetadataService:
NFSandmongodb(in progress) implementations - ValidationOverrideService, ValidationReportService:
NFSandmongodb(in progress) implementations - Repositories:
Study&User:postgresqlandsqlite(for development) implementationsValidationReport&ValidationOverride:NFSandmongodb(in progress)InvestigationFileObject,IsaTableObject(SampleFile,AssayFileAssignmentFile):NFSandmongodb(in progress)FileObject: to store data folder content.NFS(in progress) andmongodb(in progress)
Run layer¶
Runlayer definesdependency_injectorcontainer and runs an executable inpresentationlayer (submission API, submission API worker, CLI, etc.).- Initial executables are:
Submission Rest API: It uses celery async application, NFS and PostgreSQL based repositories, redis cache service and proxy authentication service.Submission Rest API Worker: Celery worker to run submission remote tasksSubmission Rest API Worker Monitor: Flower executable to monitor celery tasksCLI: Initial commandline tool namedmtbls-tools- Log filters and application configuration files are customized depends on selected presentation layer application and service implementations.
- Unit tests overrides async task, auth, and cache services. Postgresql database is also overriden by Sqlite database to run unit tests.