SpecsModelExplore
Overview
IOModel Stack
Reverse ProxyIOModel StudioYjs Realtime ServerKeycloakPostgreSQLRedis
SpecsModelExplore
IOModel Studio
OverviewStudio GuideLinks and Communications
IDiomodel.studio
DescriptionThe application (web UI and API).
Keystudio
Typedeployment
Table of contents
Studio Guide
Why it's needed
Key configuration
Deployment
Roll out Studio
Expose via Ingress

Studio Guide

IOModel Studio is the application itself — the Next.js web UI and the API that backs it. It is the component users actually interact with, and the hub that talks to every other service in the stack.

Role in the stack

Studio reads and writes to PostgreSQL, caches in Redis, authenticates users via Keycloak, and mints short-lived WebSocket tokens for the Yjs Realtime Server.

Why it’s needed

  • Product surface — serves the web UI and the REST/RPC API.
  • Orchestration — coordinates auth, persistence, caching, and realtime collaboration.
  • Stateless by design — holds no durable state locally, so it scales horizontally and restarts cleanly.
  • Key configuration

    SettingPurpose
    DATABASE_URLPostgreSQL connection string
    REDIS_URLCache / coordination endpoint
    AUTH_KEYCLOAK_ISSUEROIDC issuer for sign-in
    AUTH_URLPublic origin of the deployment
    COLLAB_JWT_SECRETSigns realtime WS tokens for the Yjs server

    Deployment

    Because Studio is stateless, the only real concern is wiring it to its dependencies and running database migrations before traffic arrives.

    A horizontally scalable Deployment behind a Service, with a one-shot migration Job:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: studio
      namespace: iomodel
    spec:
      replicas: 2
      selector: { matchLabels: { app: studio } }
      template:
        metadata: { labels: { app: studio } }
        spec:
          containers:
            - name: studio
              image: iomodel/studio:latest
              ports: [{ containerPort: 3200 }]
              envFrom: [{ secretRef: { name: studio-env } }]
              readinessProbe:
                httpGet: { path: /api/health, port: 3200 }

    Run migrations first

    Apply the migration Job (or an init container) so the schema is ready before pods serve traffic.

    Roll out Studio

    Apply the Deployment and Service; scale replicas to match load.

    Expose via Ingress

    Route external / traffic to the studio service (see the Reverse Proxy guide).

    Migrate before serving

    Always run database migrations before new Studio replicas accept traffic. Use order: start-first (Swarm) or readiness probes (Kubernetes) for zero-downtime rollouts.

    Links and Communications

    1 incoming link · 4 outgoing links · 2 workflows

    Incoming Links(1)

    Source objectLabelLink typeRelationRaw idRequiredDescription
    Reverse Proxy

    deployment.iomodel.reverse_proxy

    ingress_controller
    routes HTTPS to—linksiomodel.studio——

    Outgoing Links(4)

    Target objectLabelLink typeRelationRaw idRequiredDescription
    PostgreSQL

    deployment.iomodel.postgres

    statefulset
    reads / writes—linksiomodel.postgres——
    Redis

    deployment.iomodel.redis

    statefulset
    caches in—linksiomodel.redis——
    Keycloak

    deployment.iomodel.keycloak

    deployment
    authenticates via—linksiomodel.keycloak——
    Yjs Realtime Server

    deployment.iomodel.yjs_server

    deployment
    mints WS tokens for—linksiomodel.yjs_server——

    Related Workflows(2)

    WorkflowModelParticipant idParticipant label
    Release upgrade

    release-upgrade

    deploymentiomodel.studioIOModel Studio
    User sign-in

    sign-in

    deploymentiomodel.studioIOModel Studio
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: studio
      namespace: iomodel
    spec:
      replicas: 2
      selector: { matchLabels: { app: studio } }
      template:
        metadata: { labels: { app: studio } }
        spec:
          containers:
            - name: studio
              image: iomodel/studio:latest
              ports: [{ containerPort: 3200 }]
              envFrom: [{ secretRef: { name: studio-env } }]
              readinessProbe:
                httpGet: { path: /api/health, port: 3200 }