System overview

Architecture

How the browser client, the gateway API, the optimizer service and your AWS account fit together, and what crosses each boundary.

The pieces

Three services Optifuse runs, plus two external systems it reads from.

Client

Next.js 15, React 19, Tailwind 4
  • App Router, mostly client components because every screen is driven by a token held in the browser
  • Holds the session token in localStorage under optifuse_api_token
  • Talks only to the gateway. It never reaches GitHub or AWS directly

Gateway API

Django REST Framework
  • Exchanges the GitHub OAuth code for a session token
  • Proxies repository listing and file reads through the user GitHub grant
  • Assumes the customer IAM role and pulls X-Ray and CloudWatch data
  • Calls the optimizer and wraps its reply for the browser

Optimizer

Go service, gRPC contract in proto/optimizer.proto
  • Receives the function topology plus live metrics
  • Runs several fusion strategies over the same workload
  • Returns an OptimizationPlan: every candidate, plus its own recommendation

GitHub

External, OAuth scopes read:user and repo
  • Identity provider for sign in
  • Source of the serverless.yml that defines the function topology

Your AWS account

External, cross account IAM role
  • Read only. X-Ray traces for the call graph, CloudWatch Logs for metrics
  • Reached by role assumption, never by stored access keys

Sign in flow

1
ClientGitHub

/login sends the browser to GitHub with the client id and the scopes read:user,repo.

2
GitHubClient

GitHub redirects back to /auth/callback with a short lived code in the query string.

3
ClientGateway

The callback POSTs that code to /api/auth/github/. The gateway trades it with GitHub for an access token it keeps server side.

4
GatewayClient

The gateway returns its own session token. The client writes it to localStorage and every later request carries Authorization: Token <token>.

Analysis flow

What happens when you press Run live analysis. This is the path that needs both integrations connected.

1
ClientGateway

POST /api/simulate/live/ with { owner, repoName }. That is the whole request body. Everything else is resolved server side from the token.

2
GatewayGitHub

Reads serverless.yml from the repo to recover the declared functions and their wiring.

3
GatewayAWS

Assumes your IAM role using the external id, then queries X-Ray for the call graph and CloudWatch Logs for duration and memory.

4
GatewayOptimizer

Hands the merged topology and metrics to the Go service, which runs each fusion strategy.

5
OptimizerClient

The plan comes back wrapped as { results: { results: [...], recommended: {...} } } and the optimize page flattens it for display.

API surface

Every gateway endpoint this client calls. All except the first require the session token.

MethodPathBodyReturnsScreen
POST/api/auth/github/{ code }{ username, token }auth/callback
GET/api/repositories/-Repository[]dashboard
GET/api/repositories/{owner}/{repo}/file/-{ filename, content }repo detail
GET/api/profile/settings/-{ username, subscription, aws_role_arn, aws_external_id }settings
POST/api/profile/settings/{ aws_role_arn }{ message } | { error }settings
POST/api/simulate/live/{ owner, repoName }OptimizationPlanoptimize

The result shape

What /api/simulate/live/ returns, and the part the UI reads.

OptimizationPlan
{
  results: {
    results: [                      // one entry per algorithm
      {
        name: "NoFusion",           // always present, the baseline
        metrics: {
          total_cost_usd: number,
          latency_ms: number,
          runtime_ms: number,       // the solver's own time
          feasible: boolean         // false if constraints are breached
        },
        groups: [                   // FusionGroup, see optimizer.proto
          {
            function_ids: string[], // >1 id means these merge
            total_memory_mb: number,
            total_runtime_ms: number,
            execution_cost_usd: number
          }
        ],
        error_message?: string
      }
    ],
    recommended: { name: string }   // the backend's own pick
  }
}

Two details matter when reading this. The UI trusts recommended.name rather than picking a winner itself, because falling back to the first entry would always report NoFusion. And total_memory_mb is the sum of the members, which is an upper bound: a real fused Lambda allocates roughly its largest member, not the total.

AWS trust model

Optifuse never holds AWS keys. You deploy a CloudFormation role that trusts the Optifuse service account, guarded by an external id unique to you, so a leaked account id alone is not enough to assume it.

X-Ray

Builds the call graph between functions

  • GetTraceSummaries
  • BatchGetTraces
  • ListResourcePolicies

CloudWatch Logs

Supplies duration and memory metrics

  • DescribeLogGroups
  • StartQuery
  • StopQuery
  • GetQueryResults
  • FilterLogEvents

Every action above is a read. Nothing in the policy can create, modify or delete a resource in your account.

What is observed, and what is inferred

This page is written from the client side of the system, so it is worth being precise about the difference.

Observed in this repo

  • Every endpoint, request body and response shape listed above
  • The OAuth scopes and the token storage key
  • The full IAM policy, from the CloudFormation template on the settings page
  • The wrapped plan shape, and that NoFusion is the baseline

Inferred

  • Django REST Framework, from the Token auth scheme
  • A Go service over gRPC, from the reference to proto/optimizer.proto
  • That the gateway is what reads GitHub and AWS, rather than the optimizer
  • Which algorithms exist, since their names arrive at runtime