# Recommended Architectures

## Overview

This section presents the recommended container architecture for WorkflowGen in order to run the web portals and Windows services. There will be many references to the image configuration properties; see the [Configuration](https://docs.workflowgen.com/docker/workflowgen-image/configuration) section for information on these.

{% hint style="info" %}
This section is only about container architecture. SQL data and volumes should always be used regardless of the architecture.
{% endhint %}

See the [SQL Server Hosting Options](https://docs.workflowgen.com/docker/sql-server-hosting-options) section for information on SQL database deployments, and the [File Management](https://docs.workflowgen.com/docker/workflowgen-image/file-management) section for information on volume deployment.

## Single container

![Single container architecture](https://3571244637-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnOnQxQ9iO8Mo5-FRAX%2F-LpZW9OdKe_RrIAmiEGR%2F-LpZWP-Swmy9EPBPqx3y%2Farchitecture_wfgen4docker_-_Single_Container-crop.png?alt=media\&token=f63c4240-1658-4831-8ffa-995c97680c00)

This is the simplest architecture you can run with WorkflowGen: a single container without replicas that runs both web applications and Windows Services. Therefore, you would set the `WFGEN_START_SERVICE` environment variable to `all`. This architecture is well suited to development and test environments, but it can also be considered when the performance with a single container fits the product usage. You can't replicate the container because there should only be one instance of each WorkflowGen Windows Service running.

### Docker Compose example

This is the same example as in the [Getting Started](https://docs.workflowgen.com/docker/getting-started) section. It has one WorkflowGen container that runs every service (web applications and Windows Services).

```yaml
version: '3.7'
services:
  workflowgen:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    ports:
      - '8080:80'
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  database:
    image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
    env_file:
      - '.\database.env'
    volumes:
      - 'sqldata:C:\wfgen\sql'

volumes:
  wfgdata:
  licenses:
    external: true
  sqldata:
  
```

### Helm example

This example is different from the [Getting Started](https://docs.workflowgen.com/docker/getting-started) example. This Helm release is not scalable in the cluster. It has a pod that runs all of the WorkflowGen services (web applications and Windows services) and another pod for the database. You can use the steps in the [Getting Started](https://docs.workflowgen.com/docker/getting-started) example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.

```yaml
scalable: false

workflowgen:
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '1'
      memory: 2Gi
  config:
    WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
    WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
    WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
    WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
    WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
    WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
  secret:
    ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
    ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
    WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
    WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
    WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
  license:
    secretName: wfgen-license-secret
    items:
      - key: WorkflowGen.lic
        path: WorkflowGen.lic
  dataPvcSpec:
    accessModes:
      - ReadWriteMany
    storageClassName: azurefile
    resources:
      requests:
        storage: 50Gi
  service:
    type: LoadBalancer

database:
  fullnameOverride: wfgen-database
  nodeSelector:
    kubernetes.io/os: linux
  securityContext:
    runAsUser: 0
    runAsGroup: 0
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '500m'
      memory: 1Gi
  config:
    ACCEPT_EULA: 'Y'
    SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
    WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
    WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
    WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
  secret:
    SA_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
    WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
  volumeClaimTemplateSpec:
    accessModes:
      - ReadWriteOnce
    storageClassName: default
    resources:
      requests:
        storage: 100Gi
        
ingress:
  enabled: false

```

## Multiple web application instances, single Windows Services instance

![Multiple web application instances, single Windows services instance](https://3571244637-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnOnQxQ9iO8Mo5-FRAX%2F-LpZW9OdKe_RrIAmiEGR%2F-LpZW_gEiSMhWRL-P1eS%2Farchitecture_wfgen4docker_-_Multiple_web_apps_Single_Win_service-crop.png?alt=media\&token=44c99d6f-07e9-48c0-918c-d646093e8121)

Since there can be only one instance of each WorkflowGen Windows Service running at a time, this architecture lets you run multiple replicas of the web applications in order to scale WorkflowGen to meet your traffic and processing needs without having more instances of the Windows Services.&#x20;

You'll need to set the `WFGEN_START_SERVICE` environment variable to `web_apps` for the web applications' containers, and to `win_services` for the single container to run all of the Windows Services without web applications. This architecture is good for scaling the web portals to the traffic and processing needs, without too much pressure on the Windows Services.

### Docker Compose example

```yaml
version: '3.7'
services:
  workflowgen-web-apps:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: web_apps
    ports:
      - '8080:80'
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  workflowgen-win-services:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: win_services
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  database:
    image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
    env_file:
      - '.\database.env'
    volumes:
      - 'sqldata:C:\wfgen\sql'

volumes:
  appdata:
  licenses:
    external: true
  sqldata:
  
```

### Helm example

This is the same example as in the [Getting Started](https://docs.workflowgen.com/docker/getting-started) section. The Windows Services containers will always be in the same pod when you use the WorkflowGen Helm chart. You can use the steps in the [Getting Started](https://docs.workflowgen.com/docker/getting-started) example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.

```yaml
replicaCount: 3

workflowgen:
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '1'
      memory: 2Gi
  config:
    WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
    WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
    WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
    WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
    WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
    WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
  secret:
    ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
    ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
    WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
    WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
    WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
  license:
    secretName: wfgen-license-secret
    items:
      - key: WorkflowGen.lic
        path: WorkflowGen.lic
  dataPvcSpec:
    accessModes:
      - ReadWriteMany
    storageClassName: azurefile
    resources:
      requests:
        storage: 50Gi
  service:
    type: LoadBalancer

winServices:
  dirSync:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi
  engine:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi

database:
  fullnameOverride: wfgen-database
  nodeSelector:
    kubernetes.io/os: linux
  securityContext:
    runAsUser: 0
    runAsGroup: 0
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '500m'
      memory: 1Gi
  config:
    ACCEPT_EULA: 'Y'
    SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
    WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
    WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
    WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
  secret:
    SA_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
    WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
  volumeClaimTemplateSpec:
    accessModes:
      - ReadWriteOnce
    storageClassName: default
    resources:
      requests:
        storage: 100Gi

```

## Multiple web application instances, dedicated Windows services containers

![Multiple web application instances, dedicated Windows services containers](https://3571244637-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnOnQxQ9iO8Mo5-FRAX%2F-LpZW9OdKe_RrIAmiEGR%2F-LpZWfuqX5Sjf_HqBRKU%2Farchitecture_wfgen4docker_-_Multiple_web_apps_dedicated_win_services_container-crop.png?alt=media\&token=3077ae1d-be62-4ba8-9f7c-c462188d2084)

This recommended architecture is the most scalable. It has multiple containers for the web applications that can be scaled for increased traffic or processing needs, and has dedicated containers for each Windows Service: one for the directory synchronization service and one for the engine service. Therefore, you would set the `WFGEN_START_SERVICE` environment variable to `web_apps` for the web applications' containers, to `dir_sync` for the directory synchronization service container, and to `engine` for the engine service container. This architecture is good for high availability and high performance scenarios.

### Docker Compose example

```yaml
version: '3.7'
services:
  workflowgen-web-apps:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: web_apps
    ports:
      - '8080:80'
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  workflowgen-dir-sync-service:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: dir_sync
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  workflowgen-engine-service:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: engine
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  database:
    image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
    env_file:
      - '.\database.env'
    volumes:
      - 'sqldata:C:\wfgen\sql'

volumes:
  wfgdata:
  licenses:
    external: true
  sqldata:

```

### Helm example

This is the same example as in the [Getting Started](https://docs.workflowgen.com/docker/getting-started) section. The Windows services containers will always be in the same pod when you use the WorkflowGen Helm chart. You can use the steps in the [Getting Started](https://docs.workflowgen.com/docker/getting-started) example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.

```yaml
replicaCount: 3

workflowgen:
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '1'
      memory: 2Gi
  config:
    WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
    WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
    WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
    WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
    WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
    WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
  secret:
    ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
    ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
    WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
    WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
    WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
  license:
    secretName: wfgen-license-secret
    items:
      - key: WorkflowGen.lic
        path: WorkflowGen.lic
  dataPvcSpec:
    accessModes:
      - ReadWriteMany
    storageClassName: azurefile
    resources:
      requests:
        storage: 50Gi
  service:
    type: LoadBalancer

winServices:
  dirSync:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi
  engine:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi

database:
  fullnameOverride: wfgen-database
  nodeSelector:
    kubernetes.io/os: linux
  securityContext:
    runAsUser: 0
    runAsGroup: 0
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '500m'
      memory: 1Gi
  config:
    ACCEPT_EULA: 'Y'
    SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
    WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
    WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
    WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
  secret:
    SA_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
    WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
  volumeClaimTemplateSpec:
    accessModes:
      - ReadWriteOnce
    storageClassName: default
    resources:
      requests:
        storage: 100Gi

```
