IsUp - Architecture Overview (do.dev Integrated)

System Architecture

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                   FRONTEND                                           │
│                                                                                      │
│   ┌──────────────────────────────────────────────────────────────────────────────┐  │
│   │                        isup-dev (Next.js 16 + React 19)                       │  │
│   │                                                                               │  │
│   │   Uses: @workspace/ui, @do/catalyst, Tailwind 4, TypeScript                  │  │
│   │                                                                               │  │
│   │   ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │  │
│   │   │  Dashboard   │  │ Status Pages │  │   Landing    │  │    Docs      │    │  │
│   │   │  (Protected) │  │   (Public)   │  │   (Public)   │  │   (Public)   │    │  │
│   │   └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │  │
│   │                                                                               │  │
│   └──────────────────────────────────────────────────────────────────────────────┘  │
│                                         │                                            │
└─────────────────────────────────────────┼────────────────────────────────────────────┘

                    ┌─────────────────────┴─────────────────────┐
                    │                                           │
                    ▼                                           ▼
┌───────────────────────────────────┐       ┌───────────────────────────────────┐
│           WorkOS AuthKit          │       │          billing-dev API          │
│                                   │       │                                   │
│  • SSO / OAuth (Google, GitHub)   │       │  • Stripe subscriptions           │
│  • Session management             │       │  • Entitlements & limits          │
│  • User metadata sync             │       │  • Usage metering                 │
│  • Role-based access              │       │  • Customer portal                │
│                                   │       │                                   │
└───────────────────────────────────┘       └───────────────────────────────────┘
                    │                                           │
                    └─────────────────────┬─────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              CONVEX (Real-time Backend)                              │
│                                                                                      │
│   Shared schema from @workspace/convex                                              │
│                                                                                      │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐               │
│   │   users     │  │  monitors   │  │  incidents  │  │ statusPages │               │
│   │  (shared)   │  │  (isup)     │  │   (isup)    │  │   (isup)    │               │
│   └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘               │
│                                                                                      │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                                │
│   │alertContacts│  │organizations│  │   roles     │                                │
│   │   (isup)    │  │  (shared)   │  │  (shared)   │                                │
│   └─────────────┘  └─────────────┘  └─────────────┘                                │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

        ┌─────────────────────────────────┼─────────────────────────────────┐
        │                                 │                                 │
        ▼                                 ▼                                 ▼
┌───────────────────┐         ┌───────────────────┐         ┌───────────────────┐
│   Upstash Redis   │         │     Tinybird      │         │      Resend       │
│                   │         │   (ClickHouse)    │         │                   │
│  • Rate limiting  │         │                   │         │  • Alert emails   │
│  • Job queues     │         │  • Check results  │         │  • Status updates │
│  • Caching        │         │  • Time-series    │         │  • Notifications  │
│                   │         │  • Analytics      │         │                   │
└───────────────────┘         └───────────────────┘         └───────────────────┘

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           MONITORING WORKERS (Cloudflare)                            │
│                                                                                      │
│   ┌─────────────────────────────────────────────────────────────────────────────┐   │
│   │                        isup-checker (Cloudflare Workers)                     │   │
│   │                                                                              │   │
│   │   Deployed to: us-east, us-west, eu-west, eu-central, asia-east, oceania    │   │
│   │   Cron: Every minute (* * * * *)                                            │   │
│   │                                                                              │   │
│   │   ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                      │   │
│   │   │  HTTP Check  │  │  SSL Check   │  │  DNS Check   │                      │   │
│   │   └──────────────┘  └──────────────┘  └──────────────┘                      │   │
│   │                                                                              │   │
│   └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                      │
│   ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐                  │
│   │  Cloudflare KV   │  │ Cloudflare Queue │  │ Durable Objects  │                  │
│   │                  │  │                  │  │                  │                  │
│   │ • Monitor cache  │  │ • results-queue  │  │ • State machine  │                  │
│   │ • Last check     │  │ • incident-queue │  │ • Rate limiting  │                  │
│   │ • Config sync    │  │ • notify-queue   │  │                  │                  │
│   └──────────────────┘  └──────────────────┘  └──────────────────┘                  │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

Authentication Flow (WorkOS - Same as do-dev)

┌──────────────────────────────────────────────────────────────────────────────────────┐
│                              Authentication Flow                                      │
├──────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                       │
│   1. User visits isup.dev                                                            │
│      │                                                                                │
│      ▼                                                                                │
│   2. middleware.ts checks WorkOS session                                             │
│      │                                                                                │
│      ├── Has session ────▶ Allow access to dashboard                                 │
│      │                                                                                │
│      └── No session ────▶ Redirect to /sign-in                                       │
│                              │                                                        │
│                              ▼                                                        │
│   3. WorkOS AuthKit handles OAuth                                                    │
│      │                                                                                │
│      ├── Google OAuth                                                                │
│      ├── GitHub OAuth                                                                │
│      └── Email/Password                                                              │
│                              │                                                        │
│                              ▼                                                        │
│   4. On success, sync to Convex                                                      │
│      │                                                                                │
│      ├── Create/update user in Convex                                               │
│      ├── Assign appId: "isup"                                                        │
│      ├── Generate userId: "usr_xxx"                                                  │
│      ├── Create personal organization: "org_xxx"                                     │
│      └── Sync metadata to WorkOS                                                     │
│                              │                                                        │
│                              ▼                                                        │
│   5. Check billing-dev for entitlements                                             │
│      │                                                                                │
│      └── GET /entitlement?userId={workosUserId}                                      │
│          Returns: plan, limits, features                                             │
│                                                                                       │
└──────────────────────────────────────────────────────────────────────────────────────┘

Middleware Configuration

// apps/isup-dev/middleware.ts (same pattern as do-dev)
import { authkitMiddleware } from "@workos-inc/authkit-nextjs";

export default authkitMiddleware({
  middlewareAuth: {
    enabled: true,
    unauthenticatedPaths: [
      "/",
      "/sign-in",
      "/sign-up",
      "/pricing",
      "/docs",
      "/docs/(.*)",
      "/status/(.*)",      // Public status pages
      "/api/webhooks/(.*)",
      "/api/public/(.*)",
    ],
  },
});

export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
  ],
};

Billing Integration Flow

┌──────────────────────────────────────────────────────────────────────────────────────┐
│                              Billing Flow (via billing-dev)                           │
├──────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                       │
│   ┌─────────────┐                    ┌─────────────┐                                 │
│   │  isup-dev   │                    │ billing-dev │                                 │
│   └──────┬──────┘                    └──────┬──────┘                                 │
│          │                                  │                                         │
│          │  1. POST /checkout               │                                         │
│          │     { userId, priceId }          │                                         │
│          │─────────────────────────────────▶│                                         │
│          │                                  │                                         │
│          │  2. Returns Stripe checkout URL  │                                         │
│          │◀─────────────────────────────────│                                         │
│          │                                  │                                         │
│          │  3. User completes checkout      │       ┌─────────────┐                  │
│          │─────────────────────────────────────────▶│   Stripe    │                  │
│          │                                  │       └──────┬──────┘                  │
│          │                                  │              │                          │
│          │                                  │  4. Webhook  │                          │
│          │                                  │◀─────────────┘                          │
│          │                                  │                                         │
│          │                                  │  5. Update org plan                     │
│          │                                  │     Create entitlements                 │
│          │                                  │                                         │
│          │  6. GET /entitlement             │                                         │
│          │─────────────────────────────────▶│                                         │
│          │                                  │                                         │
│          │  7. Returns plan + limits        │                                         │
│          │◀─────────────────────────────────│                                         │
│          │                                  │                                         │
│          │  {                               │                                         │
│          │    plan: "isup-pro",             │                                         │
│          │    limits: {                     │                                         │
│          │      monitors: 50,               │                                         │
│          │      intervalMin: 60,            │                                         │
│          │      retentionDays: 365          │                                         │
│          │    },                            │                                         │
│          │    features: [                   │                                         │
│          │      "isup.access",              │                                         │
│          │      "isup.api",                 │                                         │
│          │      "isup.status_pages"         │                                         │
│          │    ]                             │                                         │
│          │  }                               │                                         │
│          │                                  │                                         │
└──────────┴──────────────────────────────────┴─────────────────────────────────────────┘

Convex Schema (IsUp Tables)

// Addition to tools/convex/convex/schema.ts

// ============================================
// IsUp Tables (appId: "isup")
// ============================================

monitors: defineTable({
  appId: v.literal("isup"),
  userId: v.id("users"),
  organizationId: v.string(),

  name: v.string(),
  type: v.union(
    v.literal("http"),
    v.literal("ping"),
    v.literal("port"),
    v.literal("keyword"),
    v.literal("ssl"),
    v.literal("dns"),
    v.literal("heartbeat")
  ),
  url: v.string(),

  intervalSeconds: v.number(),
  timeoutSeconds: v.number(),
  regions: v.array(v.string()),

  // HTTP options
  httpMethod: v.optional(v.string()),
  httpHeaders: v.optional(v.any()),
  httpBody: v.optional(v.string()),
  expectedStatusCodes: v.optional(v.array(v.number())),

  // Keyword options
  keyword: v.optional(v.string()),
  keywordType: v.optional(v.union(v.literal("present"), v.literal("absent"))),

  // Port options
  port: v.optional(v.number()),

  // SSL options
  sslExpiryAlertDays: v.optional(v.array(v.number())),

  // Thresholds
  responseTimeThreshold: v.optional(v.number()),

  // State
  status: v.union(v.literal("active"), v.literal("paused"), v.literal("deleted")),
  currentState: v.union(v.literal("up"), v.literal("down"), v.literal("degraded"), v.literal("unknown")),
  lastCheckedAt: v.optional(v.number()),
  lastStateChangeAt: v.optional(v.number()),

  // Denormalized stats
  uptimePercent24h: v.optional(v.number()),
  uptimePercent7d: v.optional(v.number()),
  uptimePercent30d: v.optional(v.number()),
  avgResponseTime24h: v.optional(v.number()),

  createdAt: v.number(),
  updatedAt: v.number(),
})
  .index("by_user", ["userId"])
  .index("by_org", ["organizationId"])
  .index("by_status", ["status"])
  .index("by_state", ["currentState"])
  .index("by_next_check", ["status", "lastCheckedAt"]),

alertContacts: defineTable({
  appId: v.literal("isup"),
  userId: v.id("users"),
  organizationId: v.string(),

  name: v.string(),
  type: v.union(
    v.literal("email"),
    v.literal("slack"),
    v.literal("discord"),
    v.literal("telegram"),
    v.literal("webhook"),
    v.literal("sms"),
    v.literal("voice")
  ),
  config: v.any(),
  isVerified: v.boolean(),
  isDefault: v.boolean(),

  createdAt: v.number(),
})
  .index("by_user", ["userId"])
  .index("by_org", ["organizationId"]),

monitorAlertContacts: defineTable({
  monitorId: v.id("monitors"),
  alertContactId: v.id("alertContacts"),
})
  .index("by_monitor", ["monitorId"])
  .index("by_contact", ["alertContactId"]),

incidents: defineTable({
  appId: v.literal("isup"),
  monitorId: v.id("monitors"),
  organizationId: v.string(),

  startedAt: v.number(),
  endedAt: v.optional(v.number()),
  durationSeconds: v.optional(v.number()),

  cause: v.string(),
  errorMessage: v.optional(v.string()),
  affectedRegions: v.array(v.string()),

  resolvedBy: v.optional(v.union(v.literal("auto"), v.literal("manual"))),
  notes: v.optional(v.string()),

  notificationsSent: v.array(v.object({
    contactId: v.id("alertContacts"),
    sentAt: v.number(),
    type: v.string(),
    success: v.boolean(),
  })),

  createdAt: v.number(),
})
  .index("by_monitor", ["monitorId"])
  .index("by_org", ["organizationId"])
  .index("by_time", ["startedAt"])
  .index("by_active", ["monitorId", "endedAt"]),

statusPages: defineTable({
  appId: v.literal("isup"),
  userId: v.id("users"),
  organizationId: v.string(),

  slug: v.string(),
  name: v.string(),
  description: v.optional(v.string()),

  customDomain: v.optional(v.string()),
  customDomainVerified: v.optional(v.boolean()),

  theme: v.optional(v.any()),
  isPublic: v.boolean(),
  passwordHash: v.optional(v.string()),
  allowIndexing: v.boolean(),

  createdAt: v.number(),
  updatedAt: v.number(),
})
  .index("by_user", ["userId"])
  .index("by_org", ["organizationId"])
  .index("by_slug", ["slug"])
  .index("by_domain", ["customDomain"]),

statusPageMonitors: defineTable({
  statusPageId: v.id("statusPages"),
  monitorId: v.id("monitors"),
  displayName: v.optional(v.string()),
  sortOrder: v.number(),
})
  .index("by_page", ["statusPageId"])
  .index("by_monitor", ["monitorId"]),

Tinybird Schema (Time-Series)

-- Check results (high-volume writes)
DATASOURCE check_results
ENGINE = MergeTree
ENGINE_SORTING_KEY monitor_id, timestamp
ENGINE_PARTITION_KEY toYYYYMM(timestamp)
ENGINE_TTL timestamp + INTERVAL 90 DAY

SCHEMA >
    monitor_id String,
    organization_id String,
    timestamp DateTime64(3),
    region String,
    status Enum8('up' = 1, 'down' = 2, 'degraded' = 3),
    response_time_ms UInt32,
    status_code Nullable(UInt16),
    error_message Nullable(String),
    dns_time_ms Nullable(UInt32),
    connect_time_ms Nullable(UInt32),
    tls_time_ms Nullable(UInt32),
    ttfb_ms Nullable(UInt32),
    ssl_expiry_date Nullable(DateTime),
    ssl_issuer Nullable(String)

-- Hourly aggregations (materialized view)
DATASOURCE check_results_hourly
ENGINE = SummingMergeTree
ENGINE_SORTING_KEY monitor_id, hour, region

SCHEMA >
    monitor_id String,
    hour DateTime,
    region String,
    check_count UInt64,
    up_count UInt64,
    avg_response_time Float64,
    max_response_time UInt32,
    min_response_time UInt32

Cloudflare Worker Architecture

Worker Structure

tools/workers/isup-checker/
├── src/
│   ├── index.ts           # Main entry
│   ├── checks/
│   │   ├── http.ts
│   │   ├── ssl.ts
│   │   ├── dns.ts
│   │   └── keyword.ts
│   ├── queue/
│   │   ├── results.ts
│   │   └── incidents.ts
│   └── utils/
│       ├── convex.ts
│       └── tinybird.ts
├── wrangler.toml
└── package.json

wrangler.toml

name = "isup-checker"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[triggers]
crons = ["* * * * *"]

[[kv_namespaces]]
binding = "MONITORS_KV"
id = "xxx"

[[queues.producers]]
queue = "isup-results"
binding = "RESULTS_QUEUE"

[[queues.producers]]
queue = "isup-incidents"
binding = "INCIDENTS_QUEUE"

[[queues.consumers]]
queue = "isup-results"
max_batch_size = 100
max_batch_timeout = 30

[env.us-east]
vars = { REGION = "us-east" }

[env.eu-west]
vars = { REGION = "eu-west" }

[env.asia]
vars = { REGION = "asia" }

Data Flow

Check Execution

1. Cron fires (every minute)


2. Worker reads monitors from KV (cached from Convex)


3. Filter monitors due for check


4. Execute checks in parallel (per region)

       ├── us-east: 50 monitors
       ├── eu-west: 50 monitors
       └── asia: 50 monitors


5. Queue results to RESULTS_QUEUE


6. Results consumer processes batch

       ├── Write to Tinybird (time-series)
       ├── Update KV state cache
       └── Check for state changes


7. If state changed → Queue to INCIDENTS_QUEUE


8. Incident consumer

       ├── Create/update incident in Convex
       ├── Get alert contacts
       └── Send notifications

Project Structure

dodotdev/
├── apps/
│   ├── do-dev/              # Existing
│   └── isup-dev/            # NEW
│       ├── app/
│       │   ├── (marketing)/
│       │   ├── (dashboard)/
│       │   ├── (status)/
│       │   └── api/
│       ├── components/
│       ├── hooks/
│       ├── lib/
│       └── package.json
├── packages/
│   ├── ui/                  # Shared
│   ├── catalyst/            # Shared
│   └── convex/              # Add IsUp tables
├── tools/
│   ├── convex/
│   │   └── convex/
│   │       ├── isup/        # NEW
│   │       │   ├── monitors.ts
│   │       │   ├── incidents.ts
│   │       │   └── statusPages.ts
│   │       └── schema.ts
│   └── workers/             # NEW
│       └── isup-checker/
└── billing-dev/             # Existing

References

On this page