vtex-io-service-runtime

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Service Runtime & Execution Model

服务运行时与执行模型

When this skill applies

适用场景

Use this skill when the main decision is how a VTEX IO backend app runs inside the
node
builder: how the
Service
entrypoint is structured, how runtime configuration is declared, and how routes, events, or GraphQL handlers are registered into the service.
  • Creating a new backend app under
    node/
  • Structuring
    node/index.ts
    as the service entrypoint
  • Defining typed
    Context
    ,
    State
    , and params contracts for handlers
  • Configuring
    service.json
    for timeout, memory, workers, and replicas
  • Troubleshooting runtime issues caused by service registration or execution model mismatches
  • Registering GraphQL handlers at the runtime level, while keeping schema and resolver design in a separate skill
Do not use this skill for:
  • deciding the app contract in
    manifest.json
  • designing custom clients or integration transport layers
  • detailed HTTP route handler behavior
  • event-specific business workflows
  • GraphQL schema or resolver modeling beyond runtime registration
当需要决策VTEX IO后端应用在
node
构建器内的运行方式时使用本指南:包括
Service
入口点的结构设计、运行时配置的声明方式,以及路由、事件或GraphQL处理器如何注册到服务中。
  • node/
    目录下创建新的后端应用
  • 搭建
    node/index.ts
    作为服务入口点
  • 为处理器定义类型化
    Context
    State
    和参数契约
  • 配置
    service.json
    的超时、内存、worker和副本参数
  • 排查服务注册或执行模型不匹配导致的运行时问题
  • 在运行时层面注册GraphQL处理器,将schema和解析器设计归到其他指南范畴
本指南不适用于以下场景:
  • 确定
    manifest.json
    中的应用契约
  • 设计自定义客户端或集成传输层
  • 详细的HTTP路由处理器行为设计
  • 特定事件的业务工作流设计
  • 运行时注册之外的GraphQL schema或解析器建模

Decision rules

决策规则

  • Treat
    node/index.ts
    as the runtime composition root of the backend app.
  • Use the
    Service
    definition to register runtime surfaces such as routes, events, and GraphQL handlers, not to hold business logic directly.
  • Keep runtime wiring explicit: context typing, client typing, route registration, and event registration should be visible at the service boundary.
  • Put execution knobs such as timeout, ttl, memory, workers, and replica limits in
    service.json
    , not inside handler code.
  • Use
    service.json
    to declare the runtime parameters the platform uses to execute the service, especially
    memory
    ,
    timeout
    ,
    ttl
    ,
    minReplicas
    ,
    maxReplicas
    ,
    workers
    ,
    routes
    ,
    events
    , and
    rateLimitPerReplica
    .
  • Use
    routes
    in
    service.json
    to expose HTTP entrypoints. Routes are private by default, so set
    public: true
    explicitly for routes that must be externally reachable.
  • Use
    smartcache: true
    only on idempotent, cacheable routes where the same response can be safely reused across repeated requests. Avoid it on personalized, authenticated, or write-oriented endpoints.
  • Use
    events
    in
    service.json
    to declare which event sources and handlers are part of the service runtime. Keep event registration in the runtime layer and event-specific business rules in dedicated event modules.
  • Use
    rateLimitPerReplica
    to shape throughput per replica for requests and events. Set a global baseline only when the service needs it, then add small explicit overrides only for expensive routes or noisy event sources.
  • Do not use
    rateLimitPerReplica
    as a substitute for redesigning expensive routes, queueing work, or moving slow operations to async processing.
  • Keep handlers focused on request or event behavior; keep runtime structure focused on bootstrapping and registration.
  • Model
    Context
    ,
    State
    , and params types deliberately so middlewares and handlers share a stable contract. Apply the same typed
    Context
    and
    State
    to middlewares so they can safely manipulate
    ctx.state
    ,
    ctx.vtex
    , and params without falling back to
    any
    .
  • If a backend app starts mixing runtime wiring, client implementation, and business rules in the same file, split those concerns before expanding the service further.
  • Although some authorization fields such as
    routes.access
    or
    routes.policies
    may live in
    service.json
    , they are primarily authorization concerns and belong in auth or security-focused skills rather than this runtime skill.
Runtime sizing heuristics:
  • These ranges are intended for partner and account-level apps. Native VTEX core services may legitimately use much higher values such as thousands of MB of memory or hundreds of replicas, but those values should not be used as defaults for custom apps.
Suggested defaults:
  • Start synchronous HTTP services with
    timeout
    between 10 and 30 seconds. For UX-facing routes, prefer 5 to 15 seconds.
  • Start
    memory
    at 256 MB.
  • Start
    workers
    at 1.
  • Use
    minReplicas: 2
    as the default for installed apps, and reserve
    minReplicas: 1
    for linked-app development contexts where the platform allows it.
  • Use
    maxReplicas: 5
    as the lowest practical starting point, since the documented minimum is
    5
    .
  • Use
    ttl
    intentionally. In VTEX IO,
    ttl
    is measured in minutes, with platform defaults and limits that differ from
    timeout
    . For partner apps, start from the default
    10
    minutes and increase intentionally up to
    60
    only when reducing cold starts matters more than allowing idle instances to sleep sooner.
Scaling ranges and exceptions:
  • Use 128 to 256 MB for simpler IO-bound services, and move to 512 MB only when there is evidence of OOM, large payload processing, or heavier libraries.
  • Increase
    workers
    to 2 to 4 only for high-throughput IO-bound workloads after measuring benefit. Avoid using more than 4 workers per instance as a default.
  • Increase
    maxReplicas
    from
    5
    toward
    10
    only when public traffic or predictable peaks justify it. Treat values above 10 as exceptions that require explicit justification and monitoring in partner apps.
  • Avoid
    timeout
    values above 60 seconds for HTTP routes; if more time is needed, redesign the flow as async work.
  • Remember that
    ttl
    has a documented minimum of
    10
    minutes and maximum of
    60
    minutes. Use higher values intentionally to reduce cold starts on low-traffic or bursty services, and avoid treating
    ttl
    like a per-request timeout.
  • For partner apps,
    rateLimitPerReplica.perMinute
    often starts in the
    60
    to
    300
    range for normal routes and in the
    10
    to
    60
    range for more expensive ones.
    rateLimitPerReplica.concurrent
    often starts between
    1
    and
    5
    .
  • node/index.ts
    作为后端应用的运行时组合根。
  • 使用
    Service
    定义注册路由、事件、GraphQL处理器等运行时表层逻辑,不要直接存放业务逻辑。
  • 保持运行时编排显式化:上下文类型、客户端类型、路由注册、事件注册都应该在服务边界可见。
  • 将超时、ttl、内存、worker、副本限制等执行参数放在
    service.json
    中,不要放在处理器代码内。
  • 使用
    service.json
    声明平台执行服务所需的运行时参数,尤其是
    memory
    timeout
    ttl
    minReplicas
    maxReplicas
    workers
    routes
    events
    rateLimitPerReplica
  • 使用
    service.json
    中的
    routes
    暴露HTTP入口点。路由默认是私有的,如需外部可访问请显式设置
    public: true
  • 仅在幂等、可缓存的路由上使用
    smartcache: true
    ,这类路由的相同响应可以安全地在重复请求中复用。个性化、需认证或写操作的端点不要开启该配置。
  • 使用
    service.json
    中的
    events
    声明服务运行时包含的事件源和处理器。将事件注册放在运行时层,特定事件的业务规则放在专用的事件模块中。
  • 使用
    rateLimitPerReplica
    调整每个副本处理请求和事件的吞吐量。仅当服务需要时设置全局基准值,之后仅为高开销路由或高频事件源添加小范围的显式覆盖配置。
  • 不要用
    rateLimitPerReplica
    替代高开销路由重构、任务排队、慢操作异步化等优化方案。
  • 保持处理器聚焦于请求或事件的处理逻辑;保持运行时结构聚焦于启动引导和注册逻辑。
  • 审慎设计
    Context
    State
    和参数类型,让中间件和处理器共享稳定的契约。为中间件应用相同的类型化
    Context
    State
    ,让它们可以安全地操作
    ctx.state
    ctx.vtex
    和参数,无需回退到
    any
    类型。
  • 如果后端应用在同一个文件中混合了运行时编排、客户端实现和业务规则,在进一步扩展服务前先拆分这些关注点。
  • 尽管
    routes.access
    routes.policies
    等授权字段可能放在
    service.json
    中,但它们主要属于授权相关内容,归属于权限或安全类指南,不属于本运行时指南范畴。
运行时大小评估启发式规则:
  • 以下取值范围适用于合作伙伴和账户级应用。VTEX原生核心服务可以使用更高的配置,比如数千MB内存或数百个副本,但这些值不应该作为自定义应用的默认值。
建议默认值:
  • 同步HTTP服务的
    timeout
    初始设置为10到30秒。面向用户体验的路由优先设置为5到15秒。
  • memory
    初始设置为256 MB。
  • workers
    初始设置为1。
  • 已安装的应用默认使用
    minReplicas: 2
    ,仅在平台允许的关联应用开发环境中使用
    minReplicas: 1
  • 最低初始
    maxReplicas
    设置为5,因为文档规定的最小值为5。
  • 按需设置
    ttl
    。在VTEX IO中,
    ttl
    以分钟为单位,平台默认值和限制与
    timeout
    不同。合作伙伴应用初始使用默认的10分钟,仅当减少冷启动比让空闲实例更快休眠更重要时,再按需上调到最多60分钟。
伸缩范围和例外情况:
  • 简单IO密集型服务使用128到256 MB内存,仅当出现OOM、大负载处理或依赖较重的库时才调整到512 MB。
  • 针对高吞吐量IO密集型工作负载,在验证收益后再将
    workers
    提升到2到4。默认不要使用超过4个worker per实例。
  • 仅当公网流量或可预测的峰值需要时,才将
    maxReplicas
    从5提升到10。合作伙伴应用中超过10的取值属于例外情况,需要明确的理由和监控支撑。
  • HTTP路由的
    timeout
    不要超过60秒;如果需要更长处理时间,将流程重设计为异步工作。
  • 注意
    ttl
    的文档规定最小值为10分钟,最大值为60分钟。按需使用更高值来减少低流量或突发流量服务的冷启动,不要将
    ttl
    当作单请求超时使用。
  • 合作伙伴应用中,普通路由的
    rateLimitPerReplica.perMinute
    初始通常在60到300范围,高开销路由在10到60范围。
    rateLimitPerReplica.concurrent
    初始通常在1到5之间。

Hard constraints

硬性约束

Constraint: The Service entrypoint must stay a runtime composition root

约束:Service入口点必须作为运行时组合根

node/index.ts
MUST define and export the VTEX IO service runtime structure, not become a catch-all file for business logic, data transformation, or transport implementation.
Why this matters
When the entrypoint mixes registration with business logic, the execution model becomes harder to reason about, handlers become tightly coupled, and changes to routes, events, or GraphQL surfaces become risky.
Detection
If
node/index.ts
contains large handler bodies, external API calls, complex branching, or data-mapping logic, STOP and move that logic into dedicated modules. Keep the entrypoint focused on typing and registration.
Correct
typescript
import type { ClientsConfig, RecorderState, ServiceContext } from '@vtex/api'
import { Service } from '@vtex/api'
import { clients, Clients } from './clients'
import { routes } from './routes'

export interface State extends RecorderState {}

export type Context = ServiceContext<Clients, State>

const clientsConfig: ClientsConfig<Clients> = {
  implementation: clients,
  options: {},
}

export default new Service<Clients, State>({
  clients: clientsConfig,
  routes,
})
Wrong
typescript
import { Service } from '@vtex/api'
import axios from 'axios'

export default new Service({
  routes: {
    reviews: async (ctx: any) => {
      const response = await axios.get('https://example.com/data')
      const transformed = response.data.items.map((item: any) => ({
        ...item,
        extra: true,
      }))

      ctx.body = transformed.filter((item: any) => item.active)
    },
  },
})
node/index.ts
必须定义并导出VTEX IO服务运行时结构,不能变成存放业务逻辑、数据转换或传输实现的大杂烩文件。
重要性
当入口点混合了注册逻辑和业务逻辑时,执行模型会更难理解,处理器之间会高度耦合,修改路由、事件或GraphQL表层逻辑的风险会很高。
检测方式
如果
node/index.ts
包含大量处理器体、外部API调用、复杂分支逻辑或数据映射逻辑,请立刻停止修改,将这些逻辑迁移到专用模块中。保持入口点聚焦于类型定义和注册逻辑。
正确示例
typescript
import type { ClientsConfig, RecorderState, ServiceContext } from '@vtex/api'
import { Service } from '@vtex/api'
import { clients, Clients } from './clients'
import { routes } from './routes'

export interface State extends RecorderState {}

export type Context = ServiceContext<Clients, State>

const clientsConfig: ClientsConfig<Clients> = {
  implementation: clients,
  options: {},
}

export default new Service<Clients, State>({
  clients: clientsConfig,
  routes,
})
错误示例
typescript
import { Service } from '@vtex/api'
import axios from 'axios'

export default new Service({
  routes: {
    reviews: async (ctx: any) => {
      const response = await axios.get('https://example.com/data')
      const transformed = response.data.items.map((item: any) => ({
        ...item,
        extra: true,
      }))

      ctx.body = transformed.filter((item: any) => item.active)
    },
  },
})

Constraint: Runtime configuration must be expressed in
service.json
, not improvised in code

约束:运行时配置必须在
service.json
中声明,不能在代码中临时定义

Resource and execution settings such as timeout, ttl, memory, workers, and replica behavior MUST be configured in
service.json
when the app depends on them.
service.json
resides inside the
node/
folder and centralizes runtime parameters such as routes, events, memory, timeout, ttl, workers, replicas, and rate limits for this service.
Why this matters
These settings are part of the service runtime contract with the platform. Hiding them in assumptions or spreading them across code makes behavior harder to predict and can cause timeouts, cold-start churn, underprovisioning, or scaling mismatches. In VTEX IO,
ttl
is especially important because it is measured in minutes and influences how aggressively service infrastructure can go idle between requests. Using the minimum
ttl
on low-traffic services can increase cold starts, because the platform is allowed to scale the service down more aggressively between bursts.
Detection
If the app depends on long-running work, concurrency, warm capacity, or specific route exposure behavior, STOP and verify that the relevant
service.json
settings are present and intentional. If the behavior is only implied in code comments or handler logic, move it into runtime configuration.
Correct
json
{
  "memory": 256,
  "timeout": 30,
  "ttl": 10,
  "minReplicas": 2,
  "maxReplicas": 10,
  "workers": 4,
  "rateLimitPerReplica": {
    "perMinute": 300,
    "concurrent": 10
  },
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    }
  }
}
Wrong
json
{
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews"
    }
  }
}
This runtime configuration is incomplete for a service that depends on explicit timeout, concurrency, rate limiting, or replica behavior, and it leaves execution characteristics undefined.
超时、ttl、内存、worker、副本行为等资源和执行设置,当应用依赖这些配置时必须在
service.json
中配置。
service.json
存放在
node/
文件夹下,集中管理该服务的路由、事件、内存、超时、ttl、worker、副本、速率限制等运行时参数。
重要性
这些设置是服务与平台之间运行时契约的一部分。将配置隐藏在假设中或分散在代码中会让行为更难预测,可能导致超时、冷启动波动、资源配置不足或伸缩不匹配。在VTEX IO中,
ttl
尤其重要,因为它以分钟为单位,会影响服务基础设施在请求间隙的空闲回收策略。 低流量服务使用最小
ttl
会增加冷启动概率,因为平台会在流量峰值间隙更激进地缩容服务。
检测方式
如果应用依赖长时运行任务、并发处理、热容量或特定路由暴露行为,请立刻停止修改,验证
service.json
中存在对应的显式配置。如果相关行为仅在代码注释或处理器逻辑中隐含,将其迁移到运行时配置中。
正确示例
json
{
  "memory": 256,
  "timeout": 30,
  "ttl": 10,
  "minReplicas": 2,
  "maxReplicas": 10,
  "workers": 4,
  "rateLimitPerReplica": {
    "perMinute": 300,
    "concurrent": 10
  },
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    }
  }
}
错误示例
json
{
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews"
    }
  }
}
如果服务依赖显式的超时、并发、速率限制或副本行为,该运行时配置是不完整的,会导致执行特性未定义。

Constraint: Route exposure must be explicit in the runtime contract

约束:路由暴露必须在运行时契约中显式声明

Every HTTP route exposed by the service MUST be declared in
service.json
with an intentional visibility choice. Do not rely on implicit defaults when the route should be private or public. Routes are private by default, so always set
public: true
explicitly when the route must be externally reachable.
Why this matters
Route visibility is part of the runtime contract of the service. If exposure is ambiguous, a route can be published with the wrong accessibility, which creates security risk for private handlers and integration failures for routes expected to be public.
Detection
If a route exists in the service runtime, STOP and verify that it is declared in
service.json
and that
public
matches the intended exposure. If the route is consumed only by trusted backoffice or app-to-app flows, default to checking that it is private before expanding access.
Correct
json
{
  "routes": {
    "status": {
      "path": "/_v/status/health",
      "public": true,
      "smartcache": true
    },
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    }
  }
}
Wrong
json
{
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews"
    }
  }
}
This route leaves visibility implicit, so the runtime contract does not clearly communicate whether the endpoint is meant to be public or protected.
服务暴露的每个HTTP路由都必须在
service.json
中声明,并明确指定可见性。当路由需要设为私有或公开时,不要依赖隐式默认值。 路由默认是私有的,所以当路由需要外部可访问时一定要显式设置
public: true
重要性
路由可见性是服务运行时契约的一部分。如果暴露规则不明确,路由发布后可能出现错误的访问权限,为私有处理器带来安全风险,也会导致预期公开的路由集成失败。
检测方式
如果服务运行时中存在某个路由,请立刻停止修改,验证它已在
service.json
中声明,且
public
取值符合预期的暴露规则。如果路由仅受信任的后台或应用间流程调用,在扩展访问权限前默认检查它是否为私有。
正确示例
json
{
  "routes": {
    "status": {
      "path": "/_v/status/health",
      "public": true,
      "smartcache": true
    },
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    }
  }
}
错误示例
json
{
  "routes": {
    "reviews": {
      "path": "/_v/api/reviews"
    }
  }
}
该路由的可见性是隐式的,运行时契约无法清晰说明端点是公开的还是受保护的。

Constraint: Typed context and state must match the handlers registered in the runtime

约束:类型化上下文和状态必须与运行时注册的处理器匹配

The service MUST define
Context
,
State
, and handler contracts that match the routes, events, or GraphQL handlers it registers.
Why this matters
Untyped or inconsistent runtime contracts make middleware composition fragile and allow handlers to rely on state or params that are never guaranteed to exist.
Detection
If middlewares or handlers use
ctx.state
,
ctx.clients
,
ctx.vtex
, or params fields without a shared typed contract, STOP and introduce or fix the runtime types before adding more handlers.
Correct
typescript
import type { ParamsContext, RecorderState, ServiceContext } from '@vtex/api'

interface State extends RecorderState {
  reviewId?: string
}

type CustomContext = ServiceContext<Clients, State, ParamsContext>

export async function getReview(ctx: CustomContext) {
  ctx.state.reviewId = ctx.vtex.route.params.id
  ctx.body = { id: ctx.state.reviewId }
}
Wrong
typescript
export async function getReview(ctx: any) {
  ctx.state.reviewId = ctx.params.review
  ctx.body = { id: ctx.state.missingField.value }
}
服务必须定义
Context
State
和处理器契约,与它注册的路由、事件或GraphQL处理器匹配。
重要性
无类型或不一致的运行时契约会让中间件组合变得脆弱,也会让处理器依赖永远无法保证存在的状态或参数。
检测方式
如果中间件或处理器使用
ctx.state
ctx.clients
ctx.vtex
或参数字段时没有共享的类型化契约,请立刻停止修改,在添加更多处理器前引入或修复运行时类型。
正确示例
typescript
import type { ParamsContext, RecorderState, ServiceContext } from '@vtex/api'

interface State extends RecorderState {
  reviewId?: string
}

type CustomContext = ServiceContext<Clients, State, ParamsContext>

export async function getReview(ctx: CustomContext) {
  ctx.state.reviewId = ctx.vtex.route.params.id
  ctx.body = { id: ctx.state.reviewId }
}
错误示例
typescript
export async function getReview(ctx: any) {
  ctx.state.reviewId = ctx.params.review
  ctx.body = { id: ctx.state.missingField.value }
}

Preferred pattern

推荐模式

Recommended file layout:
text
node/
├── index.ts
├── clients/
│   └── index.ts
├── routes/
│   └── index.ts
├── events/
│   └── index.ts
├── graphql/
│   └── index.ts
└── middlewares/
    └── validate.ts
Minimal service runtime pattern:
typescript
import type { ClientsConfig, RecorderState, ServiceContext } from '@vtex/api'
import { Service } from '@vtex/api'
import { clients, Clients } from './clients'
import { routes } from './routes'

export interface State extends RecorderState {}

export type Context = ServiceContext<Clients, State>

const clientsConfig: ClientsConfig<Clients> = {
  implementation: clients,
  options: {},
}

export default new Service<Clients, State>({
  clients: clientsConfig,
  routes,
})
Minimal
service.json
pattern:
json
{
  "memory": 256,
  "timeout": 30,
  "ttl": 10,
  "minReplicas": 2,
  "maxReplicas": 5,
  "workers": 1,
  "rateLimitPerReplica": {
    "perMinute": 120,
    "concurrent": 4
  },
  "routes": {
    "status": {
      "path": "/_v/status/health",
      "public": true,
      "smartcache": true
    },
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    }
  },
  "events": {
    "orderCreated": {
      "sender": "vtex.orders-broadcast",
      "topics": ["order-created"],
      "rateLimitPerReplica": {
        "perMinute": 60,
        "concurrent": 2
      }
    }
  }
}
Use the service entrypoint to compose runtime surfaces, then push business behavior into handlers, clients, and other focused modules. If
routes/index.ts
or
events/index.ts
grows too large, split it by domain such as
routes/orders.ts
or
events/catalog.ts
and keep the index file as a small registry.
推荐的文件结构:
text
node/
├── index.ts
├── clients/
│   └── index.ts
├── routes/
│   └── index.ts
├── events/
│   └── index.ts
├── graphql/
│   └── index.ts
└── middlewares/
    └── validate.ts
最简服务运行时模式:
typescript
import type { ClientsConfig, RecorderState, ServiceContext } from '@vtex/api'
import { Service } from '@vtex/api'
import { clients, Clients } from './clients'
import { routes } from './routes'

export interface State extends RecorderState {}

export type Context = ServiceContext<Clients, State>

const clientsConfig: ClientsConfig<Clients> = {
  implementation: clients,
  options: {},
}

export default new Service<Clients, State>({
  clients: clientsConfig,
  routes,
})
最简
service.json
模式:
json
{
  "memory": 256,
  "timeout": 30,
  "ttl": 10,
  "minReplicas": 2,
  "maxReplicas": 5,
  "workers": 1,
  "rateLimitPerReplica": {
    "perMinute": 120,
    "concurrent": 4
  },
  "routes": {
    "status": {
      "path": "/_v/status/health",
      "public": true,
      "smartcache": true
    },
    "reviews": {
      "path": "/_v/api/reviews",
      "public": false
    }
  },
  "events": {
    "orderCreated": {
      "sender": "vtex.orders-broadcast",
      "topics": ["order-created"],
      "rateLimitPerReplica": {
        "perMinute": 60,
        "concurrent": 2
      }
    }
  }
}
使用服务入口点编排运行时表层逻辑,然后将业务逻辑下沉到处理器、客户端和其他专用模块中。 如果
routes/index.ts
events/index.ts
变得太大,按领域拆分,比如
routes/orders.ts
events/catalog.ts
,保持索引文件作为小型注册表。

Common failure modes

常见故障模式

  • Putting business logic directly into
    node/index.ts
    .
  • Treating
    service.json
    as optional when runtime behavior depends on explicit resource settings.
  • Setting
    ttl
    too low and causing the service to sleep too aggressively between bursts of traffic.
  • Enabling
    smartcache
    on personalized or write-oriented routes and risking incorrect cache reuse across requests.
  • Registering routes, events, or GraphQL handlers without a clear typed
    Context
    and
    State
    .
  • Mixing runtime composition with client implementation details.
  • Letting one service entrypoint accumulate unrelated responsibilities across HTTP, events, and GraphQL without clear module boundaries.
  • 直接将业务逻辑放在
    node/index.ts
    中。
  • 当运行时行为依赖显式资源设置时,将
    service.json
    当作可选配置。
  • ttl
    设置太低,导致服务在流量峰值间隙过于激进地休眠。
  • 在个性化或写操作路由上开启
    smartcache
    ,导致请求间错误复用缓存。
  • 注册路由、事件或GraphQL处理器时没有定义清晰的类型化
    Context
    State
  • 混合运行时编排与客户端实现细节。
  • 单个服务入口点累积了HTTP、事件、GraphQL等不相关的职责,没有清晰的模块边界。

Review checklist

审核清单

  • Is
    node/index.ts
    acting as a runtime composition root rather than a business-logic file?
  • Are routes, events, and GraphQL handlers registered explicitly and cleanly?
  • Does
    service.json
    express the runtime behavior the app actually depends on?
  • Are
    Context
    ,
    State
    , and params types shared consistently across handlers?
  • Are runtime concerns separated from client implementation and business logic?
  • node/index.ts
    是否作为运行时组合根使用,而非存放业务逻辑的文件?
  • 路由、事件和GraphQL处理器是否显式、清晰地注册?
  • service.json
    是否声明了应用实际依赖的运行时行为?
  • Context
    State
    和参数类型是否在所有处理器之间一致共享?
  • 运行时关注点是否与客户端实现和业务逻辑分离?

Reference

参考资料