Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Appsmith Admin Guide

Generated June 2026 from appsmithorg/appsmith at 293e1b6

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is for the people who run, secure, scale, and extend Appsmith: platform administrators, DevOps/SRE engineers, security reviewers, and developers who want to understand the codebase. It covers Appsmith's architecture, the complete configuration reference, deployment topologies, security hardening, day-2 operations, and internals down to the plugin SPI and reactive request pipeline.

For app-building (widgets, queries, bindings, publishing), see the companion Appsmith User Guide — this document links to it where the two overlap.

Scope and edition note. Appsmith builds two editions from one repository: Community Edition (CE), Apache-2.0 licensed (appsmith/appsmith-ce), and Enterprise Edition (EE) (appsmith/appsmith-ee), which layers SAML/enterprise SSO, granular RBAC, audit logs, and business features behind a license key. The codebase expresses this as a ce/ (community) vs. ee/ (enterprise) split throughout both client and server. This guide centers on CE and flags EE-only surfaces.


Table of Contents

  1. Executive Summary
  2. Architecture
  3. Requirements
  4. Configuration Mastery
  5. Deployment
  6. Security
  7. Operations
  8. Troubleshooting
  9. Developer Internals
  10. Code Quality and Conventions
  11. Potential Improvements
  12. Contributing
  13. Quick Reference

1. Executive Summary

Appsmith is a self-hosted, open-source low-code platform for building internal applications. Administrators deploy a single artifact — the Appsmith container — and end users build and run web apps inside it against their own databases and APIs.

What you operate:

Aspect Summary
Distribution A single "fat" Docker image bundling the web editor, application server, real-time service, and databases, supervised by supervisord. Also packaged as a Helm chart, AWS AMI, and platform-specific manifests.
Backend Java 25, Spring Boot WebFlux (fully reactive, non-blocking on Netty), Spring Security, with a Maven multi-module layout and a plugin SPI for datasource connectors.
Frontend React 17 + Redux + Redux-Saga, TypeScript, built with Yarn workspaces; a sandboxed evaluation worker drives reactive bindings.
Real-Time Service (RTS) A Node.js/TypeScript service for AST parsing, evaluation helpers, and Git operations.
Persistence Application metadata and encrypted credentials in a bundled database (MongoDB, migrating to PostgreSQL), Redis for caching/sessions, and a Git working tree on disk. All under one persistent volume: /appsmith-stacks.
Edge Caddy v2 inside the container terminates HTTP(S), auto-provisions TLS, and routes to the internal services.

Key operational facts to internalize early:

  • One volume holds everything. /appsmith-stacks contains configuration (docker.env), the embedded databases' data, Git working copies, and logs. Back it up; protect it; never let two containers share it.
  • Two secrets are load-bearing. APPSMITH_ENCRYPTION_PASSWORD and APPSMITH_ENCRYPTION_SALT encrypt stored datasource credentials. Lose or change them and every saved credential becomes undecryptable.
  • The server is reactive. No thread-per-request; concurrency comes from the event loop. Memory (JVM heap) is the lever that matters most for a single container.
  • Migrations run on boot. The server applies schema migrations automatically at startup — always back up before upgrading the image.

2. Architecture

2.1 The single-container ("fat container") model

The default Appsmith deployment is one container running many processes, orchestrated by supervisord. This trades the operational simplicity of "one thing to run" for a denser footprint.

                        Internet / LAN
                              │
                        host:8080 → container:80
                              │
        ┌─────────────────────────────────────────────────────┐
        │  Appsmith container (appsmith/appsmith-ce | -ee)      │
        │                                                       │
        │   supervisord  (PID 1 process manager)                │
        │     ├── editor   → Caddy v2  :80   (TLS, routing)     │
        │     │      ├── /api/*  → backend :8080                │
        │     │      ├── /rts/*  → rts     :8091                │
        │     │      └── /*      → React build (static)         │
        │     ├── backend  → Java Spring WebFlux  :8080         │
        │     ├── rts      → Node.js RTS          :8091         │
        │     ├── postgres → embedded PostgreSQL  :5432         │
        │     ├── mongodb  → embedded MongoDB     :27017        │
        │     └── redis    → embedded Redis       :6379         │
        │                                                       │
        │   Persistent volume: /appsmith-stacks                 │
        │     ├── configuration/docker.env                      │
        │     ├── data/ (mongo, postgres)                       │
        │     ├── git-storage/  (per-app Git working copies)    │
        │     └── logs/                                         │
        └─────────────────────────────────────────────────────┘

The six supervised programs are literally named editor, backend, rts, postgres, mongodb, and redis (see deploy/docker/fs/opt/appsmith/templates/supervisord/). The container's healthcheck.sh verifies each is RUNNING and additionally curls the editor (http://localhost/) and the server health endpoint (http://localhost:8080/api/v1/health).

Note

Bundled databases are a convenience for single-node installs. For production and Kubernetes, you typically disable the embedded databases and point Appsmith at external, managed MongoDB/PostgreSQL/Redis via the connection-string environment variables (§4). This is what makes horizontal scaling and proper backups feasible.

2.2 Boot sequence

ENTRYPOINT
  └── deploy/docker/fs/opt/appsmith/entrypoint.sh
        ├── set up nss_wrapper (run as arbitrary non-root UID)
        ├── configure HTTP(S)_PROXY / NO_PROXY
        ├── init_env_file:  render /appsmith-stacks/configuration/docker.env
        │      from current APPSMITH_* env + templates/docker.env.sh
        ├── caddy-reconfigure.mjs: generate Caddy config from env (domain, TLS)
        └── start_app.sh → supervisord (reads /etc/supervisor/supervisord.conf,
               includes per-process *.conf from templates/supervisord/)

The env file is rendered once at boot by merging the process environment (any APPSMITH_*/MONGO_* variables you pass to the container) with templates/docker.env.sh defaults, and persisted to /appsmith-stacks/configuration/docker.env. On subsequent restarts, that file is the source of truth — which is why you edit it (or pass new env vars) and restart to change configuration.

2.3 Backend: reactive Spring on a multi-module Maven build

The server (app/server) is a Maven reactor with these modules:

Module Responsibility
appsmith-server The Spring Boot WebFlux application: controllers, services, security, domains, migrations.
appsmith-interfaces Shared interfaces/contracts between server and plugins.
appsmith-plugins The 25 datasource connector modules (one per plugin).
appsmith-git Git operations library (JGit-based) used for app version control.
reactive-caching A reactive caching abstraction (Redis-backed).

The application uses spring-boot-starter-webflux (not Spring MVC), spring-boot-starter-security (reactive security filter chain), spring-boot-starter-data-mongodb-reactive and spring-boot-starter-data-redis-reactive, spring-boot-starter-aop (cross-cutting telemetry/feature aspects under server/aspect), and spring-boot-starter-mail. Java version is 25 (<java.version>25</java.version>).

Because it is reactive, every controller method returns a Reactor publisher — Mono<T> for single results, Flux<T> for streams — and runs non-blocking on Netty. server.shutdown=graceful with a 20-second drain phase means in-flight requests complete before the JVM exits (important for rolling updates).

2.4 The REST API surface

All endpoints are versioned under /api/v1. The controller layer (server/controllers) maps to these resource roots:

Resource root Controller Domain
/api/v1/health HealthCheckController Liveness/readiness probe.
/api/v1/login, /logout (security) Authentication.
/api/v1/users UserController Users, invites, profile.
/api/v1/workspaces WorkspaceController Workspaces (teams).
/api/v1/tenants OrganizationController Instance/organization settings.
/api/v1/applications ApplicationController Applications.
/api/v1/pages PageController Pages within an app.
/api/v1/layouts LayoutController Page layout / DSL.
/api/v1/actions ActionController Queries/actions.
/api/v1/collections/actions ActionCollectionController JS Objects.
/api/v1/datasources DatasourceController Saved datasource connections.
/api/v1/plugins PluginController Available connector plugins.
/api/v1/git, /git/applications, /git/artifacts GitController App version control.
/api/v1/themes ThemeController App theming.
/api/v1/import, /saas RestApiImportController, SaasController Import (e.g. cURL) / SaaS auth.
/api/v1/libraries CustomJSLibController Custom JS libraries.
/api/v1/consolidated-api ConsolidatedAPIController A single call that returns all data needed to bootstrap an app view (page-load optimization).
/api/v1/admin InstanceAdminController Instance admin settings.
/api/v1/product-alert ProductFeatureAlertController Product alerts/banners.
/api/v1/search-entities SearchEntityController Global entity search.
/api/v1/app-templates ApplicationTemplateController Template gallery.
/api/v1/usage-pulse UsagePulseController Usage heartbeat.
/api/v1/assets AssetController Uploaded assets/files.

Tip

The consolidated-api endpoint is a deliberate performance optimization: instead of the client firing a dozen requests to render an app, it batches the bootstrap data into one round trip. If you see a single large request on app load, that's it.

2.5 Frontend: reactive evaluation in the browser

The client (app/client) is a React 17 SPA using Redux for state and Redux-Saga for all asynchronous side effects (API calls, evaluation orchestration, Git operations). Sagas follow the watcher/worker pattern — a rootSaga forks watcher sagas that takeLatest/takeEvery on dispatched actions and spawn worker sagas which call the API client classes (src/api/*Api, src/ce/api/*Api, each extending a base Api/API class) and put success/error actions.

The platform's defining client feature is the evaluation engine: a sandboxed web worker (src/workers/Evaluation) that maintains a dependency map (workers/common/DependencyMap) of every binding, widget property, query, and JS variable. When any value changes, it recomputes exactly the dependent nodes and re-renders — this is the reactivity users experience. A linting plugin (plugins/Linting) and a Tern-based language service (workers/Tern) provide inline error-checking and field-aware autocomplete in the code editors (CodeMirror 5).

Three layout systems coexist: fixedlayout (pixel grid), autolayout (responsive reflow), and anvil (the newer Section/Zone responsive system paired with the WDS widget family). A parallel ce/ vs ee/ source tree implements the community/enterprise split.

2.6 The Real-Time Service (RTS)

app/client/packages/rts is a separate Node.js/TypeScript service (default port 8091, APPSMITH_RTS_PORT). It runs the server-side AST work (packages/ast), evaluation helpers, and Git plumbing that benefits from a JS runtime, and exposes internal routes (e.g. a git POST /reset). Caddy proxies /rts/* to it. It is started by supervisord (run-rts.sh → node bundle/server.js) and is not a public, user-facing API.

2.7 Datasource plugin architecture

Each connector under app/server/appsmith-plugins/ is an independent Maven module implementing the plugin SPI defined in appsmith-interfaces. A plugin provides a PluginExecutor that knows how to (a) build/test a datasource connection, (b) execute an action against it, and (c) describe its form/template. The server discovers and loads plugins, so adding a connector is additive and isolated.

The 25 bundled plugins: postgresPlugin, mysqlPlugin, mssqlPlugin, oraclePlugin, snowflakePlugin, redshiftPlugin, databricksPlugin, mongoPlugin, arangoDBPlugin, dynamoPlugin, firestorePlugin, elasticSearchPlugin, redisPlugin, restApiPlugin, graphqlPlugin, amazons3Plugin, awsLambdaPlugin, googleSheetsPlugin, smtpPlugin, openAiPlugin, anthropicPlugin, googleAiPlugin, appsmithAiPlugin, saasPlugin, jsPlugin.

Note

This is the same "core + provider-plugin ecosystem" shape as other integration platforms: the platform defines the contract once, and each connector is a thin, swappable implementation. Operationally, this means a single misbehaving connector is isolated to its plugin module.


3. Requirements

3.1 Host sizing

Profile CPU Memory Disk Notes
Evaluation (single container, bundled DBs) 1–2 vCPU 2–4 GB 10 GB Fine for trials and small teams.
Small production (single container) 2–4 vCPU 4–8 GB 20+ GB Bundled or external DBs; tune JVM heap.
Production HA (Kubernetes) per-pod requests 500m CPU / 3000Mi memory (chart default) Scale pods External DBs + RWX PVC Use external MongoDB/PostgreSQL/Redis.

3.2 Network and ports

Port (container) Service Exposure
80 Caddy (edit/view, API, RTS) The only port you publish.
443 Caddy TLS (when a custom domain is set) Publish for HTTPS.
8080 Java server Internal only.
8091 RTS Internal only.
27017 / 5432 / 6379 Mongo / Postgres / Redis Internal only (or external endpoints).

Outbound: Appsmith must reach the datasources users connect to, your SMTP server (if email is enabled), and — unless telemetry is disabled — Appsmith's cloud services for template fetching and anonymized usage pulses.

3.3 Persistent storage

A durable volume mounted at /appsmith-stacks is required. On Kubernetes use a ReadWriteMany-capable StorageClass (the chart defaults to accessModes: [ReadWriteMany], size: 10Gi, reclaimPolicy: Retain). EFS is supported via the chart's persistence.efs options.


4. Configuration Mastery

Appsmith is configured almost entirely through APPSMITH_* environment variables. At boot these are rendered into /appsmith-stacks/configuration/docker.env; on Kubernetes they come from the applicationConfig map (or a referenced secretName) in the Helm values. Spring maps them onto application-ce.properties keys.

Caution

Do not confuse runtime config with build-time client variables. Names like NODE_ENV, PUBLIC_URL, WDS_SOCKET_*, REACT_APP_*, BUILD_PATH, and INLINE_RUNTIME_CHUNK (seen in app/client/config/) configure the React build and webpack dev server — they are for developing the client, not for operating a deployed instance. Runtime configuration is the APPSMITH_* set below.

4.1 Required / core

Variable Default Purpose
APPSMITH_ENCRYPTION_PASSWORD — Required. Secret used to encrypt stored datasource credentials. Set once to a long random string.
APPSMITH_ENCRYPTION_SALT — Required. Salt paired with the encryption password.
APPSMITH_CUSTOM_DOMAIN empty Public domain. When set, Caddy auto-provisions Let's Encrypt TLS.
APPSMITH_DISABLE_TELEMETRY false* Disable anonymized usage telemetry. (*The env template ships false; application-ce.properties defaults the Spring side to true when unset.)

4.2 Databases and cache

Variable Purpose
APPSMITH_DB_URL Primary metadata DB connection (MongoDB URI form, e.g. mongodb://user:pass@host:27017/appsmith).
APPSMITH_MONGODB_URI Alternative Mongo URI; if set, it is promoted to APPSMITH_DB_URL at boot.
APPSMITH_MONGODB_USER / APPSMITH_MONGODB_PASSWORD Embedded-Mongo credentials.
APPSMITH_POSTGRES_DB_URL PostgreSQL connection (the platform is migrating its metadata store to Postgres).
APPSMITH_PG_DATABASE Postgres database name (default appsmith).
APPSMITH_REDIS_URL Redis connection (redis://:password@host:6379). Sessions and cache.
APPSMITH_REDIS_PASSWORD Redis password.
APPSMITH_REDIS_GIT_URL Redis URL used for Git-related coordination.
APPSMITH_ENABLE_EMBEDDED_DB Toggle the in-container database. Set to disable when using external DBs.

Tip

For production, set the three connection URLs to external managed services and disable the embedded databases. This decouples your data lifecycle (backups, HA, scaling) from the Appsmith container and is a prerequisite for running more than one replica.

4.3 Authentication and SSO

Variable Purpose
APPSMITH_ADMIN_EMAILS Comma-separated emails granted instance super-admin.
APPSMITH_FORM_LOGIN_DISABLED Disable email/password login (force SSO).
APPSMITH_SIGNUP_DISABLED Disable open self-signup.
APPSMITH_SIGNUP_ALLOWED_DOMAINS Restrict signup to listed email domains.
APPSMITH_OAUTH2_GOOGLE_CLIENT_ID / _SECRET / _REDIRECT_URI Google OAuth SSO.
APPSMITH_OAUTH2_GITHUB_CLIENT_ID / _SECRET GitHub OAuth SSO.
APPSMITH_OAUTH2_OIDC_CLIENT_ID / _SECRET Generic OIDC SSO.
APPSMITH_OAUTH2_ALLOWED_DOMAINS (Deprecated, see SIGNUP_ALLOWED_DOMAINS) restrict OAuth logins by domain.
APPSMITH_DISABLE_EMBEDDED_KEYCLOAK Turn off the bundled Keycloak (used for SAML/enterprise SSO).
APPSMITH_KEYCLOAK_DB_URL / _USERNAME / _PASSWORD / _DRIVER External database for Keycloak.
APPSMITH_LICENSE_KEY Enterprise license key (EE).

4.4 Email (SMTP)

Variable Purpose
APPSMITH_MAIL_ENABLED Master switch for outbound email (invites, password resets).
APPSMITH_MAIL_HOST / APPSMITH_MAIL_PORT SMTP server.
APPSMITH_MAIL_USERNAME / APPSMITH_MAIL_PASSWORD SMTP auth.
APPSMITH_MAIL_FROM / APPSMITH_REPLY_TO From/Reply-To addresses.
APPSMITH_MAIL_SMTP_AUTH true/false — enable SMTP AUTH.
APPSMITH_MAIL_SMTP_TLS_ENABLED true/false — STARTTLS.

4.5 Security and limits

Variable Default Purpose
APPSMITH_ALLOWED_FRAME_ANCESTORS 'self' * (template) CSP frame-ancestors — which domains may embed Appsmith in an iframe. Set to a specific allowlist (or 'none') to control embedding.
APPSMITH_DISABLE_IFRAME_WIDGET_SANDBOX false Whether the Iframe widget runs without the browser sandbox. Keep false.
APPSMITH_RATE_LIMIT — Request rate limiting.
APPSMITH_RECAPTCHA_SITE_KEY / _SECRET_KEY / _ENABLED — Google reCAPTCHA for login/signup hardening.
APPSMITH_CODEC_SIZE 150 (MB) Max in-memory request/response size for the reactive codec (spring.codec.max-in-memory-size). Raise for very large payloads/imports.
APPSMITH_PLUGIN_MAX_RESPONSE_SIZE_MB 5 Cap on a single query response size.

Warning

APPSMITH_ALLOWED_FRAME_ANCESTORS defaults in the env template to 'self' *, which permits embedding from any origin. If you do not intend to embed Appsmith apps elsewhere, tighten this to 'self' or a specific domain allowlist to prevent clickjacking.

4.6 JVM, logging, telemetry, and domain

Variable Purpose
APPSMITH_JAVA_ARGS Extra JVM flags, e.g. -Xms1g -Xmx2g. The primary lever for server memory.
APPSMITH_JAVA_HEAP_ARG Heap sizing argument.
APPSMITH_GIT_ROOT Git working-copy root. Default /appsmith-stacks/git-storage.
APPSMITH_LOG_DIR Log directory (under the stacks volume).
APPSMITH_CLIENT_LOG_LEVEL Browser console log level (debug/error).
APPSMITH_VERBOSE_LOGGING_ENABLED Verbose server logging.
APPSMITH_SENTRY_DSN / _ENVIRONMENT, APPSMITH_SERVER_SENTRY_DSN / _ENVIRONMENT Sentry error reporting (client/server).
APPSMITH_SEGMENT_KEY / APPSMITH_SEGMENT_CE_KEY Product analytics keys.
APPSMITH_DISABLE_MONITORING / APPSMITH_MONITORING / APPSMITH_NEW_RELIC_ACCOUNT_ENABLE APM/monitoring toggles.
APPSMITH_CLOUD_SERVICES_BASE_URL Base URL for Appsmith cloud services (templates, signatures).
APPSMITH_CUSTOM_DOMAIN Public domain → triggers Caddy TLS.
APPSMITH_VERSION_ID / APPSMITH_VERSION_SHA / APPSMITH_VERSION_RELEASE_DATE Build/version stamps (set by the image).

Tip

The full, authoritative list of recognized keys is the platform's environment-variable documentation; the Helm chart's applicationConfig schema explicitly notes its enumerated keys are "common starting points and are not exhaustive." Treat the tables above as the operationally important subset.


5. Deployment

The repository's reference compose file (deploy/docker/docker-compose.yml) is intentionally minimal:

services:
  appsmith:
    image: index.docker.io/appsmith/appsmith-ce:release
    container_name: appsmith
    ports:
      - "8080:80"
    environment:
      APPSMITH_ENCRYPTION_PASSWORD: <long-random-secret>
      APPSMITH_ENCRYPTION_SALT: <long-random-secret>
    volumes:
      - ./stacks:/appsmith-stacks

Operational tasks:

docker compose up -d            # start / apply config changes
docker compose pull && docker compose up -d   # upgrade
docker logs -f appsmith         # tail logs
docker exec -it appsmith bash   # shell into the container

To enable HTTPS, set APPSMITH_CUSTOM_DOMAIN to your domain, publish port 443, and point DNS at the host — Caddy obtains and renews the certificate automatically.

The chart lives in deploy/helm. Key characteristics from values.yaml:

  • Workload: StatefulSet by default (workload.kind); switches to Deployment when autoscaling is enabled. Default image.repository: appsmith/appsmith-ee, tag latest.
  • Persistence: PVC with ReadWriteMany, 10Gi, Retain reclaim policy; EFS and existing-claim options provided.
  • Bundled dependencies (subcharts): Bitnami redis, mongodb (replicaset), and postgresql (the Postgres subchart primarily backs Keycloak). Each can be disabled to use external services.
  • MongoDB topology options: classic Bitnami replicaset, or the newer MongoDBCommunity operator path (mongodbCommunity + mongodbOperator, a 3.7.0 preview for fresh installs).
  • Exposure: Service (default ClusterIP, port 80) and optional Ingress (class nginx, TLS via cert-manager/self-signed/custom secrets).
  • Scaling: HPA (autoscaling) or KEDA (keda), mutually exclusive; PodDisruptionBudget enabled with minAvailable: 1.
  • Resources: default requests cpu: 500m, memory: 3000Mi.
  • Config: applicationConfig map of APPSMITH_* vars, or reference an existing secret via secretName. Custom CA certs via customCAcert.
helm install appsmith ./deploy/helm \
  --namespace appsmith --create-namespace \
  --set applicationConfig.APPSMITH_ENCRYPTION_PASSWORD=<secret> \
  --set applicationConfig.APPSMITH_ENCRYPTION_SALT=<secret> \
  --set applicationConfig.APPSMITH_CUSTOM_DOMAIN=appsmith.example.com

Important

For any multi-replica deployment you must externalize state: point APPSMITH_DB_URL/APPSMITH_POSTGRES_DB_URL/APPSMITH_REDIS_URL at shared, managed databases, and use a ReadWriteMany volume for /appsmith-stacks. Two replicas sharing a non-RWX volume or each running their own embedded DB will corrupt or diverge state.

5.3 Other targets

deploy/ also ships AWS AMI/Packer images, an Ansible playbook (deploy/ansible), DigitalOcean and Heroku manifests, and AWS CloudFormation/AMI assets. These wrap the same container and configuration model.


6. Security

6.1 Secrets and credential encryption

  • Datasource credentials are stored encrypted using APPSMITH_ENCRYPTION_PASSWORD + APPSMITH_ENCRYPTION_SALT. Manage these like database root passwords: long, random, stored in a secret manager, never rotated casually (rotation invalidates all stored credentials).
  • On Kubernetes, supply secrets via secretName (an existing Secret) rather than inline applicationConfig, and consider the chart's External Secrets Operator integration (externalSecrets.enabled).

6.2 Authentication hardening

  • Disable open signup in shared/production instances: APPSMITH_SIGNUP_DISABLED=true, or restrict with APPSMITH_SIGNUP_ALLOWED_DOMAINS.
  • Force SSO by disabling form login (APPSMITH_FORM_LOGIN_DISABLED=true) once OAuth/OIDC/SAML is configured.
  • Enable reCAPTCHA (APPSMITH_RECAPTCHA_*) to harden the login/signup surface against automated abuse.
  • Reactive Spring Security (server/authentication/handlers) drives the OAuth2 login flows for Google/GitHub/OIDC; EE adds SAML via embedded Keycloak.

6.3 Network and embedding

  • Terminate TLS at Caddy (custom domain) or at an upstream LB/Ingress; never expose the internal :8080/:8091 ports.
  • Lock down APPSMITH_ALLOWED_FRAME_ANCESTORS to prevent clickjacking unless you intentionally embed apps.
  • Keep APPSMITH_DISABLE_IFRAME_WIDGET_SANDBOX=false so user-authored Iframe widgets remain sandboxed.

6.4 Query safety

  • Bound values in SQL queries are sent as prepared-statement parameters by default — keep this on. Treat any datasource that disables prepared statements as a SQL-injection review item.
  • Use least-privilege datasource accounts (read-only for dashboards). Appsmith executes queries with whatever rights the configured account has.

6.5 Runtime posture

  • The container supports running as an arbitrary non-root UID via nss_wrapper (set securityContext.runAsNonRoot/runAsUser on K8s). The image build also strips setuid/setgid bits.
  • Restrict egress to only the datasources, SMTP, and (if telemetry stays on) Appsmith cloud services your instance needs.

Caution

Because end users can write JavaScript and connect arbitrary datasources, treat an Appsmith instance as a powerful tool: scope who can create datasources, segment workspaces by trust boundary, and put the instance behind your SSO and network controls.


7. Operations

7.1 Health and liveness

Check How
Process health docker exec appsmith /opt/appsmith/healthcheck.sh — verifies each supervised process is RUNNING and curls editor + server.
Server health endpoint curl http://localhost:8080/api/v1/health (internal) or https://<domain>/api/v1/health.
Supervisor status docker exec appsmith supervisorctl status.

7.2 Logs

Logs land under /appsmith-stacks/logs/ (and APPSMITH_LOG_DIR). Supervisor multiplexes each process's stdout/stderr to the container's main stream via a custom event listener, so docker logs appsmith shows interleaved, per-process-labeled output.

Note

A known community item (#41876) notes that on Kubernetes the supervisord stdout prefix can interfere with Caddy access-log parsing. Track it if you build log pipelines that parse Caddy output.

7.3 Backup and restore

Appsmith ships an in-container control utility (appsmithctl, implemented in app/client/packages/rts/src/ctl) with backup, restore, export_db, and import_db subcommands.

# Create a backup archive (written under the stacks volume)
docker exec appsmith appsmithctl backup

# Restore from a backup archive
docker exec appsmith appsmithctl restore

A backup captures the metadata database and configuration. For a belt-and-suspenders approach, also snapshot the entire /appsmith-stacks volume (which additionally includes Git working copies under git-storage/).

Important

Run a backup before every upgrade. The server applies schema migrations on startup; a pre-upgrade backup is your rollback path.

7.4 Database migration tooling (MongoDB → PostgreSQL)

The image includes helpers for the metadata-store migration and Postgres maintenance: pg-upgrade.sh, pg-utils.sh, run-postgres.sh, appsmith_hba.conf, the supervisord postgres.conf/mongodb.conf, and mongodb-fixer.sh. If you are moving an existing MongoDB-backed instance forward, follow the official migration runbook and back up first — both data paths exist in the codebase during the transition.

7.5 Diagnostics and performance capture

For incident response the container bundles JVM diagnostics scripts:

Script Purpose
diagnostics.sh Collect a diagnostics bundle.
memory-analysis.sh, record-heap-dump.sh Heap usage / heap dump.
record-thread-dump.sh, thread-profile-start.sh / thread-profile-stop.sh Thread dumps / profiling.
JFR-recording-24-hours.sh 24-hour Java Flight Recorder capture.
auto_heal.sh Auto-recovery hook (APPSMITH_AUTO_HEAL).
generate-infra-details.sh Gather host/infra details for support.

7.6 Upgrades

docker exec appsmith appsmithctl backup     # 1. back up
docker compose pull                          # 2. fetch new image
docker compose up -d                         # 3. recreate (migrations run on boot)
docker exec appsmith /opt/appsmith/healthcheck.sh   # 4. verify

On Kubernetes the StatefulSet/Deployment rolling update plus graceful shutdown drains in-flight requests; gate rollout on the readiness/health probe.


8. Troubleshooting

Symptom: container starts then exits, logs show Missing info.json / Missing MongoDB server.jar

Cause: Running a hand-built image without the proper build script artifacts. Solution: Use the official appsmith/appsmith-ce/-ee images (or the documented multi-arch build script). These files are baked at build time.

Symptom: healthcheck.sh reports a process not RUNNING

Cause: One supervised service (backend/editor/rts/db) failed to start — commonly the JVM OOM-killed, or an external DB URL is wrong. Solution: docker exec appsmith supervisorctl status to find the failed program, then read its log under /appsmith-stacks/logs/. For the backend, check memory and APPSMITH_JAVA_ARGS; for DBs, verify connection URLs.

Symptom: datasource credentials invalid after restart/upgrade

Cause: APPSMITH_ENCRYPTION_PASSWORD/APPSMITH_ENCRYPTION_SALT changed. Solution: Restore the original values. If lost, credentials must be re-entered for every datasource. Prevention: Pin these secrets permanently.

Symptom: TLS not provisioning for a custom domain

Cause: DNS not pointing at the host, port 443 not published, or domain mismatch. Solution: Confirm APPSMITH_CUSTOM_DOMAIN, publish 443, ensure A/AAAA records resolve to the host so Caddy can complete the ACME challenge.

Symptom: large import or query fails with a payload/size error

Cause: Response/request exceeds the reactive codec limit or plugin cap. Solution: Raise APPSMITH_CODEC_SIZE (MB) and/or APPSMITH_PLUGIN_MAX_RESPONSE_SIZE_MB; restart.

Symptom: server slow / periodic restarts under load

Cause: JVM heap pressure inside the container. Solution: Increase container memory and set APPSMITH_JAVA_ARGS="-Xms<n> -Xmx<n>". Capture a heap dump (record-heap-dump.sh) if it recurs. Move page-load queries to return less data.

Symptom: OAuth/Google redirect loop or mismatch

Cause: Redirect URI / domain not aligned with the deployed URL. Solution: Set APPSMITH_CUSTOM_DOMAIN and APPSMITH_OAUTH2_GOOGLE_REDIRECT_URI to match, and register the redirect URI with the identity provider.

Symptom: can't run more than one replica without data issues

Cause: Replicas using embedded DBs or a non-RWX volume. Solution: Externalize MongoDB/PostgreSQL/Redis and use a ReadWriteMany volume (§5.2).


9. Developer Internals

9.1 Repository layout

app/
  server/                      Java Spring WebFlux backend (Maven reactor)
    appsmith-server/           main app: controllers, services, domains, migrations, security
    appsmith-interfaces/       shared contracts (plugin SPI)
    appsmith-plugins/          25 datasource connector modules
    appsmith-git/              JGit-based Git operations
    reactive-caching/          reactive Redis cache abstraction
  client/                      React + Redux + Redux-Saga SPA (Yarn workspaces)
    src/
      api/, ce/api/, ee/api/   API client classes (extend base Api/API)
      sagas/, ce/sagas/        redux-saga side-effect orchestration
      workers/Evaluation/      sandboxed reactive evaluation engine
      workers/common/DependencyMap/  dependency graph
      plugins/Linting/         inline lint of bindings
      widgets/, widgets/wds/   classic + WDS widget families
      layoutSystems/           fixedlayout, autolayout, anvil
      pages/Editor/, pages/AppIDE/  the builder IDE
      ce/, ee/                 community vs enterprise split
    packages/
      rts/                     Node.js Real-Time Service (+ appsmithctl in src/ctl)
      ast/                     JS AST parsing
      design-system/           ads, ads-old, widgets, widgets-old, theming, headless
      dsl/                     page DSL transforms/migrations
deploy/
  docker/                      Dockerfile fs/, supervisord, Caddy, ops scripts, compose
  helm/                        Kubernetes chart
  ansible/, aws/, aws_ami/, digital_ocean/, heroku/, packer/

9.2 Request lifecycle (end to end)

User action in editor/viewer
   → Redux action dispatched
   → watcher saga (takeLatest/takeEvery) forks a worker saga
   → worker `call`s an *Api client class
   → HTTP request to /api/v1/<resource>
   → Caddy → backend :8080
   → Spring WebFlux controller (@RequestMapping(Url.X)) returns Mono/Flux
   → reactive service layer → reactive Mongo/Redis or a plugin PluginExecutor (for datasource queries)
   → ResponseDTO serialized back
   → worker saga `put`s SUCCESS/ERROR action → Redux store updates
   → evaluation worker recomputes dependent bindings → React re-renders

9.3 The page DSL and migrations

An application's pages are stored as a DSL (a serializable widget tree). The packages/dsl module and layoutSystems/common/DSLConversions handle DSL transforms and version migrations so older apps keep working as the widget schema evolves. Server-side, server/migrations applies metadata-store schema migrations on boot.

9.4 Import/export internals

Applications serialize to a portable JSON via the exports/ and imports/ server packages (exportable/importable artifact model). This underpins app export/import, partial import/export, Git serialization, and the template gallery. Datasource secrets are excluded from exports by design.

9.5 Writing a new datasource plugin

To add a connector: create a new Maven module under app/server/appsmith-plugins/, declare it in the plugins POM, implement the PluginExecutor contract from appsmith-interfaces (connection build/test, action execution, datasource/template metadata), and provide the editor form config. The platform discovers and loads it like the 25 existing connectors — no changes to core controllers required.


10. Code Quality and Conventions

  • Reactive end to end (server). Blocking calls are avoided in the WebFlux pipeline; data access uses reactive Mongo/Redis drivers. Reviewers should reject blocking I/O introduced into reactive flows.
  • CE/EE separation. Both client and server use parallel ce//ee/ trees so enterprise code overlays community code without forking. New community features land in ce/; enterprise overrides extend them.
  • Saga-centric side effects (client). Async logic lives in sagas, not components; components stay declarative and read from the Redux store. This keeps side effects testable and cancellable (takeLatest).
  • Typed contracts. TypeScript across the client; the API client classes centralize endpoint definitions, so the REST surface has a single client-side source of truth per resource.
  • Heavy automated testing. The client uses Cypress (app/client/cypress) and Playwright (app/client/playwright) for end-to-end coverage and Jest for unit tests; the server has extensive JUnit integration tests (appsmith-server/src/test), including DSL-migration and import/export fixtures.
  • Generators and templates. The client includes scaffolding generators (app/client/generators) for new widgets, enforcing structural consistency across the large widget catalog.

Note

AST-based static extraction yields little structured metadata for this stack (Java is not parsed by the extractor, and the TypeScript monorepo's barrel exports and decorator/registry patterns hide the real surface). The authoritative surfaces are the controller @RequestMapping constants (UrlCE), the plugin module list, the widget directory tree, and the APPSMITH_* env set — all enumerated directly from source in this guide.


11. Potential Improvements

These are observations for operators and contributors, derived from the codebase and the public issue tracker — not defects in your installation.

  • Complete the MongoDB → PostgreSQL migration. Two metadata-store data paths and a suite of pg-*/mongodb-fixer scripts coexist during the transition. Operators on older instances should plan the migration; the dual-path code is extra surface area until retired.
  • Lighten the single-container footprint. Bundling the editor, server, RTS, and three databases in one image is excellent for onboarding but heavy for production. Externalizing databases (already supported) should be the documented default for anything beyond evaluation.
  • Kubernetes log parsing. The supervisord stdout prefix vs. Caddy access-log issue (#41876) is worth resolving for clean log pipelines.
  • Widget polish. Tracked UX items include the required-marker rendering on Select widgets (#41734) and an editor dark mode (#41858).
  • Consolidate widget families. The classic and WDS/Anvil widget sets overlap; converging them reduces maintenance and user confusion over which widget to use.

12. Contributing

  • Local development (per the README and contributions/CodeContributionsGuidelines.md): run the client (app/client, Yarn 3 workspaces, Node 24) and server (app/server, Java 25 + Maven) separately for fast iteration, against local databases.
  • Code of Conduct and Contribution Guide live at the repo root (CODE_OF_CONDUCT.md, CONTRIBUTING.md); server-specific guidelines under contributions/ServerCodeContributionsGuidelines.
  • Where things go: new connectors → appsmith-plugins/; new widgets → app/client/src/widgets/ (use the generator); community features → ce/ trees; tests are expected (Cypress/Playwright/Jest client-side, JUnit server-side).
  • License: Apache 2.0.

13. Quick Reference

Supervised processes (inside the container)

Program Service Port
editor Caddy v2 (routing, TLS, static client) 80 / 443
backend Java Spring WebFlux server 8080
rts Node.js Real-Time Service 8091
postgres Embedded PostgreSQL 5432
mongodb Embedded MongoDB 27017
redis Embedded Redis 6379

Key paths (persistent volume)

Path Contents
/appsmith-stacks/configuration/docker.env Rendered runtime config.
/appsmith-stacks/data/ Embedded database data.
/appsmith-stacks/git-storage/ Per-app Git working copies.
/appsmith-stacks/logs/ Process logs.

Essential commands

docker exec appsmith supervisorctl status        # process health
docker exec appsmith /opt/appsmith/healthcheck.sh # full health check
docker exec appsmith appsmithctl backup           # back up
docker exec appsmith appsmithctl restore          # restore
curl -fsS http://localhost:8080/api/v1/health     # server liveness (internal)

Minimum production checklist

  • [ ] APPSMITH_ENCRYPTION_PASSWORD / APPSMITH_ENCRYPTION_SALT set to fixed secrets and stored safely.
  • [ ] External MongoDB/PostgreSQL/Redis configured; embedded DBs disabled.
  • [ ] ReadWriteMany persistent volume for /appsmith-stacks; backups scheduled.
  • [ ] TLS via custom domain (Caddy) or upstream Ingress; internal ports not exposed.
  • [ ] SSO configured; APPSMITH_SIGNUP_DISABLED (or allowed-domains) set; form login disabled if SSO-only.
  • [ ] APPSMITH_ALLOWED_FRAME_ANCESTORS tightened from the permissive default.
  • [ ] JVM heap sized (APPSMITH_JAVA_ARGS); host memory adequate.
  • [ ] Health probe wired into your orchestrator; pre-upgrade backup step in your runbook.

API base

All REST endpoints are under /api/v1/. Health: GET /api/v1/health. See §2.4 for the resource map.

Editions

CE (appsmith-ce) EE (appsmith-ee)
License Apache 2.0 Commercial (license key)
SSO Google/GitHub/OIDC OAuth + SAML / enterprise (Keycloak)
Access control Core roles Granular RBAC
Extras — Audit logs, business features, support