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
/login sends the browser to GitHub with the client id and the scopes read:user,repo.
GitHub redirects back to /auth/callback with a short lived code in the query string.
The callback POSTs that code to /api/auth/github/. The gateway trades it with GitHub for an access token it keeps server side.
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.
POST /api/simulate/live/ with { owner, repoName }. That is the whole request body. Everything else is resolved server side from the token.
Reads serverless.yml from the repo to recover the declared functions and their wiring.
Assumes your IAM role using the external id, then queries X-Ray for the call graph and CloudWatch Logs for duration and memory.
Hands the merged topology and metrics to the Go service, which runs each fusion strategy.
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.
| Method | Path | Body | Returns | Screen |
|---|---|---|---|---|
| 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 } | OptimizationPlan | optimize |
The result shape
What /api/simulate/live/ returns, and the part the UI reads.
{
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
Tokenauth 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