System Architecture
What this is. The product/system architecture: which service owns what, how the two backends relate, where data actually lives, and the tenancy model. For infrastructure (clusters, regions, deploy, observability) see Infrastructure & Environments; for how we build with AI see the AI Engineering Strategy (a different "architecture" β methodology, not product).
Confidence. Verified 2026-06-03 by reading the live repos at their default-branch HEAD (
sandbox,backend-services,superco-consumer,migrations-tool, frontends, mobile). Items that could not be confirmed from the served code are marked unconfirmed. Somesandboxdev-stack details differ between the served branch and PRsandbox#13β flagged inline.Last updated: 2026-06-03 Β· Owner: Engineering Lead
1. The two backendsβ
BeWith runs two backends that split the world by product line and by era:
superco-consumerβ a PHP / Yii2 monolith (yii2-app-basic). One app serves the public consumer site, API V1, and the admin app. It is the system of record: it owns the primary relational database (ebdb) and its schema. Serves the Israeli product line (coing.co).backend-servicesβ a NestJS / TypeScript monorepo of ~27 independently-deployed apps (apps/*, each its own container/port), inter-service RPC via@MessagePattern. This is "API v2" β where new (international) work happens.
The two are bridged asynchronously over SQS (Β§4) and share concepts (organizations, communities, members), but are separate runtimes with separate primary stores.
(Clientβbackend edges are the dominant paths; some clients call both. The PHPβNode bridge runs over the consumer_system / consumer_management SQS queues, Β§4.)
2. Repo β what it ownsβ
| Repo | Stack | Role | Confidence |
|---|---|---|---|
superco-consumer | PHP / Yii2 | Consumer monolith: public site + API V1 + admin; owns ebdb + its schema (Yii migrations) | verified |
backend-services | NestJS / TS monorepo | API v2, ~27 independently-deployed apps, RPC via @MessagePattern | verified |
migrations-tool | NestJS / TS | Separate ETL / data CLI (Mongoose + TypeORM + Bedrock/Anthropic) β not the schema source of truth | verified |
sqs-consumer | TS | SQS worker(s) | verified |
organization-dashboard | Next.js 13 / React + MUI | Customer-facing organization dashboard | verified |
support-tool-frontend | React (CRA) | Internal support / super-admin tool | verified |
management-webapp | Next.js 13 / React | Client surfaces (uses NEXT_PUBLIC_BACKEND_V2_URL); embedded as iframes in the consumer scheduler | role verified; iframe-embedding unconfirmed |
superco-management | Angular 8.2 | Deprecated admin frontend | verified |
leaders-app | Flutter | Event operations β ticket/card scanning, revenue view, messaging | verified |
consumer-mobile | Flutter (coing) | Consumer mobile app (Firebase auth/crashlytics, i18n) | app verified; "outsourced / brandable white-label per community" unconfirmed |
consumer-php-base | Dockerfile (php:7.4-fpm) | Base image only β app code is superco-consumer | verified |
3. Data-store boundaryβ
The headline correction: "everything is Mongo" is stale. MySQL is the system of record; Mongo is API v2's working store.
| Store | Owner / users | Holds | Source of truth for |
|---|---|---|---|
MySQL ebdb | superco-consumer (Yii2) | Core consumer entities β organizations, communities, groups, users/members, permissions | Yes β the OLTP system of record. Schema = ~407 Yii migrations in superco-consumer/migrations/, applied on deploy via php yii migrate |
| MongoDB | backend-services (API v2, Mongoose-first) | API-v2-owned domains β members/events/stats and denormalized/secondary data | For API-v2-owned domains only; not for the core consumer entities |
| Redis | both (yii2-redis on PHP; cache-manager/redis on Node) | Cache / sessions | n/a (cache) |
| OpenSearch | backend-services + migrations-tool | Search / index | n/a (derived) |
backend-services is the dual-store service: its package.json carries both @nestjs/typeorm + mysql2 and @nestjs/mongoose + mongodb, plus redis and @opensearch-project/opensearch. superco-consumer is MySQL-only (+ Redis cache).
4. Async β SQSβ
Cross-service async is SQS. The queues created in the local stack (sandbox/localstack/init-sqs.sh) β the authoritative list:
- PHP β API-v2 bridge (standard):
consumer_system,consumer_management. - Channel queues (FIFO):
email,otp_email,sms,otp_sms,whatsapp,webhooks,orders_sync,payme_witdrawals(sic),notificaitons_campaigns(sic) β drive notifications and integrations. - Internal fan-out (standard):
service_communication_user,service_communication_groups,service_communication_user_groups,service_communication_notifications.
Consumed by backend-services (@aws-sdk/client-sqs + sqs-consumer) and sqs-consumer; queue URLs wired via AWS_*_QUEUE_URL env vars. (The two misspelled queue names are the real, created names β preserved here so they match infra.)
5. Tenancy / identity modelβ
The hierarchy found in the Yii models:
Organization β Community β Group β User / Member
- A user belongs at the organization level:
users.organization_id, withUsers::findByPhoneOrEmail(?orgId, ?phone, ?email)scoping lookups byorganization_id+ email/phone. So identity is keyed by (email/phone, organization). - Supporting tables:
Organizations,OrganizationsCommunities,Communities,CommunitiesAdmins,CommunitiesGroups,Groups,UsersGroups,UsersPermissions. - Roles: super-admin and community-admin (
UsersPermissions). Community membership is modelled viaapp\models\v2\members\Member+MembersManager, synced to API v2. - "Leader" appears as a role / default name (
default_leader_name) β not a separate tenancy tier (despiteleaders-appbeing a dedicated client).
6. Local development stack (sandbox)β
sandbox/docker-compose.yml brings the system up locally:
mysqldbβmysql:8(containermysql8-dev); create DBebdb(per README;superco-consumerdefaultsRDS_DB_NAME ?? 'ebdb').redisβredis:5.0.14.mongodb8βmongo:8.0(port 27018). Note: on the served branch,mongodb5(mongo:5, port 27017) is still present; the "Mongo 5 removed, Mongo 8 only" change appears to live on PRsandbox#13(not yet on the served ref).localstackβSERVICES=sqs(the queues in Β§4).phpβ built fromconsumer-php-base:sandbox, bind-mountssuperco-consumeras the app code.infra-mcpβ a Claude Code MCP server exposing read-only tools (mysqlRunSelect,mongoRunFind,mongoRunAggregateReadOnly,redisRead) and gated write tools (mysqlRunExecute,mongoWrite,redisWrite) over MySQL/Mongo/Redis. Note: it exists as a full sub-project, but on the served branch it is not yet wired as a compose service (its README references amcpprofile +infra.shahead of the serveddocker-compose.yml) β likely lands with PRsandbox#13.
Unconfirmed: the Mongo working-DB name. The claim is develop; the served code only shows MONGO_INITDB_DATABASE=dev.
7. Deploy & infrastructureβ
Not duplicated here β see Infrastructure & Environments for clusters, regions, the tag-driven deploy, and observability. In brief, corroborated from superco-consumer/.github/workflows/: tag-triggered deploys (fr-prod-* β Frankfurt ECS, eu-central-1, ECR service-superco-consumer-ecr, ECS cluster-prod; ir-staging-* β Ireland EKS; us-prod-* β us-east-1 EKS), and php yii migrate runs as part of the FR deploy.
Open items / to verifyβ
management-webappiframe-embedding inside the consumer scheduler β role confirmed, embedding mechanism not found in served code.consumer-mobile"outsourced / brandable white-label per community" β Flutter app confirmed; the white-label/branding claim not evidenced in the manifest.- Mongo working-DB name (
developvsdev). sandbox#13deltas (Mongo-5 removal,infra-mcpas a compose service) β confirm once merged, then drop the "served-ref" caveats in Β§6.- Exact MySQLβMongo domain split inside API v2 (which domains are Mongo-owned vs read-models).