forge-cost-optimizer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseForge Cost Optimizer
Forge成本优化器
Optimize Forge apps for lower platform consumption while preserving correctness, security, and maintainability. This skill turns Atlassian's Forge cost optimization guidance into an actionable agent workflow.
在确保正确性、安全性和可维护性的前提下,优化Forge应用以降低平台资源消耗。本技能将Atlassian的Forge成本优化指南转化为可执行的Agent工作流。
Source Guidance
参考指南
Base recommendations on Atlassian's official guide: https://developer.atlassian.com/platform/forge/optimise-forge-costs/
If live Forge documentation tools are available, search the Forge docs for the exact module or API before changing code that depends on current manifest syntax, bridge APIs, storage APIs, trigger filters, or Forge Remote behavior.
优化建议基于Atlassian官方指南:https://developer.atlassian.com/platform/forge/optimise-forge-costs/
如果有可用的实时Forge文档工具,在修改依赖于当前清单语法、bridge API、存储API、触发器过滤器或Forge Remote行为的代码之前,请先搜索Forge文档查找对应的模块或API。
Core Principle
核心原则
Prioritize changes that reduce unnecessary work:
- Avoid invocations entirely — move safe work to UI Kit / Custom UI frontend, use context from the bridge, replace polling with events, add trigger filters.
- Do less work per invocation — bulk API calls, field selection, source-side filtering, pagination, early exits, bounded concurrency.
- Reduce billed data volume — trim resolver payloads, reduce KVS reads/writes, avoid large log payloads, use entity properties where appropriate.
- Tune compute cost — right-size , reduce duration, offload only when the operational trade-off is justified.
memoryMiB
Never reduce costs by weakening authorization, exposing secrets to the frontend, skipping required validation, dropping necessary error handling, or making data stale beyond the user's business requirements.
优先选择能减少不必要工作的更改:
- 完全避免调用 — 将安全的工作转移到UI Kit / Custom UI前端,使用bridge提供的上下文信息,用事件替换轮询,添加触发器过滤器。
- 减少每次调用的工作量 — 批量API调用、字段选择、源端过滤、分页处理、提前退出、限制并发数。
- 减少计费数据量 — 精简解析器返回结果、减少KVS读写操作、避免大日志负载、在合适场景使用实体属性。
- 优化计算成本 — 合理配置、缩短执行时长,仅在业务权衡合理时才进行工作卸载。
memoryMiB
绝不能通过弱化授权、向前端暴露密钥、跳过必要验证、移除必要错误处理,或让数据过期超出用户业务需求的方式来降低成本。
When Triggered
触发场景
When the user asks to optimize an existing Forge app, immediately inspect the app before asking questions unless the target app directory is ambiguous.
Default behavior is audit-first: complete the cost optimization audit, present prioritized recommendations, and ask the user whether they want the agent to make the recommended changes. Do not modify files during the initial audit unless the user explicitly requested implementation in the same prompt, such as "make the changes", "apply the optimizations", "fix these issues", or "update the code".
Read, in order:
- /
manifest.yml— functions, modules, triggers, scheduled triggers, remotes, resources, permissions, endpoint mappings,manifest.yaml.memoryMiB - — dependencies, scripts, Forge package versions.
package.json - Backend/resolver code — , handlers referenced by the manifest, storage usage, API calls, logging, async control flow.
src/** - Frontend code — UI Kit or Custom UI resources, bridge usage, patterns, render lifecycle, caching, payload needs.
invoke() - Any tests or fixtures that describe behavior to preserve.
After the audit, offer clear next-step options such as implementing all quick wins, implementing selected high-impact changes, or collecting usage measurements first. If the user explicitly requested implementation upfront, make safe, localized improvements after the audit findings are understood and explain trade-offs.
当用户要求优化现有Forge应用时,除非目标应用目录不明确,否则应立即检查应用,无需先询问问题。
默认行为为先审计:完成成本优化审计,展示优先级排序的建议,然后询问用户是否希望Agent执行推荐的更改。初始审计过程中不要修改文件,除非用户在同一请求中明确要求实施,例如“进行更改”“应用优化”“修复这些问题”或“更新代码”。
按以下顺序读取文件:
- /
manifest.yml— 函数、模块、触发器、定时触发器、远程服务、资源、权限、端点映射、manifest.yaml配置。memoryMiB - — 依赖项、脚本、Forge包版本。
package.json - 后端/解析器代码 — 目录、清单中引用的处理器、存储使用情况、API调用、日志记录、异步控制流。
src/** - 前端代码 — UI Kit或Custom UI资源、bridge使用情况、模式、渲染生命周期、缓存、负载需求。
invoke() - 任何描述需保留行为的测试或测试夹具。
审计完成后,提供清晰的后续选项,例如实施所有快速优化项、实施选定的高影响更改,或先收集使用数据。如果用户预先明确要求实施,则在理解审计结果后进行安全、局部的改进,并解释相关权衡。
Optimization Workflow
优化工作流
Step 1: Establish the Cost Profile
步骤1:确定成本概况
Identify which cost drivers the app likely uses:
| Driver | Inspect | Common signals |
|---|---|---|
| Function GB-seconds | | many resolver calls, slow sequential APIs, high |
| Invocations | frontend | calls on render, chatty UI, scheduled polling, broad event subscriptions |
| KVS / Custom Entities | | writes on every request, loops over keys, low TTL cache churn, large values |
| Logs | | full event/API payload logging, debug logs in hot paths |
| Forge SQL | SQL client usage | frequent compute requests, long queries, oversized stored data |
| Remote / egress | | external polling, compute offload candidates, Runs on Atlassian implications |
When usage metrics are unavailable, mark estimates as qualitative: , , , or .
HighMediumLowUnknown识别应用可能使用的成本驱动因素:
| 成本驱动因素 | 检查内容 | 常见信号 |
|---|---|---|
| 函数GB秒数 | | 大量解析器调用、缓慢的顺序API请求、高 |
| 调用次数 | 前端 | 渲染时调用、频繁交互的UI、定时轮询、宽泛的事件订阅 |
| KVS / 自定义实体 | | 每次请求都执行写入、遍历键值、短TTL缓存频繁更新、大值存储 |
| 日志 | | 记录完整事件/API负载、热点路径中的调试日志 |
| Forge SQL | SQL客户端使用情况 | 频繁的计算请求、长查询、过大的存储数据 |
| 远程服务/出口流量 | | 外部轮询、适合卸载的计算任务、Runs on Atlassian相关影响 |
当无法获取使用指标时,将估计值标记为定性描述:、、或。
高中低未知Step 2: Find No-Invocation Opportunities
步骤2:寻找无需调用的优化机会
Prefer removing function invocations over making them cheaper.
Check for:
- Resolver calls that only fetch product context. Replace with:
- UI Kit: from
useProductContext()@forge/react - UI Kit or Custom UI: from
view.getContext()@forge/bridge
- UI Kit:
- Read-only Jira/Confluence API calls routed through a resolver even though user-context access is acceptable. Consider /
requestJira()fromrequestConfluence().@forge/bridge - Formatting, sorting, grouping, client-safe validation, or UI-only transformation in resolvers. Move to frontend when data is already authorized for the context user.
- calls inside render bodies, unbounded effects, repeated event handlers, or multiple calls on page load that can be cached or batched.
invoke()
Keep logic in the backend when it requires , Forge storage, secrets, external credentials, cross-user authorization checks, or sensitive business rules.
asApp()优先消除函数调用,而非降低调用成本。
检查以下场景:
- 仅获取产品上下文的解析器调用。替换为:
- UI Kit:中的
@forge/reactuseProductContext() - UI Kit或Custom UI:中的
@forge/bridgeview.getContext()
- UI Kit:
- 即使允许用户上下文访问,仍通过解析器路由的只读Jira/Confluence API调用。可考虑使用中的
@forge/bridge/requestJira()。requestConfluence() - 解析器中的格式化、排序、分组、客户端安全验证或仅UI相关的数据转换。当数据已针对上下文用户授权时,将这些操作转移到前端。
- 渲染体内、无界副作用、重复事件处理程序或页面加载时的多次调用,这些可通过缓存或批量处理优化。
invoke()
当逻辑需要、Forge存储、密钥、外部凭证、跨用户授权检查或敏感业务规则时,应保留在后端。
asApp()Step 3: Optimize Triggers and Scheduling
步骤3:优化触发器与调度
Check , , and modules.
scheduledTriggertriggerwebtriggerRecommended changes:
- Increase scheduled trigger intervals when business requirements allow (→
fiveMinutes→hour→day).week - Replace scheduled polling of Atlassian product changes with product events.
- Replace scheduled polling of external services with inbound webhooks via Forge web triggers when the external service supports webhooks.
- Add manifest to suppress irrelevant product events before invocation.
filter.expression - Add for Jira triggers that would otherwise process events caused by the app itself.
filter.ignoreSelf: true - Add cheap early exits at the top of handlers before API calls, storage reads, or expensive transforms.
- Use Forge Realtime instead of frontend polling loops that repeatedly invoke resolvers waiting for backend state changes.
检查、和模块。
scheduledTriggertriggerwebtrigger推荐更改:
- 在业务需求允许的情况下,增加定时触发器的间隔(→
fiveMinutes→hour→day)。week - 用产品事件替换定时轮询Atlassian产品变更的机制。
- 当外部服务支持webhook时,用Forge web trigger接收的入站webhook替换定时轮询外部服务的机制。
- 在清单中添加,在调用前过滤无关的产品事件。
filter.expression - 为Jira触发器添加,避免处理应用自身触发的事件。
filter.ignoreSelf: true - 在处理器顶部添加低成本的提前退出逻辑,避免执行后续的API调用、存储读取或昂贵的数据转换。
- 使用Forge Realtime替代前端轮询循环,避免反复调用解析器等待后端状态变更。
Step 4: Optimize API and Data Fetching
步骤4:优化API与数据获取
Every API request inside a function contributes to duration. Look for:
- N+1 calls. Replace per-item fetches with bulk endpoints or search APIs that return requested fields.
- Missing ,
fields,expand, orlimitconstraints. Request only what the app uses.maxResults - Filtering after fetching all data. Push filters to JQL, CQL, REST query parameters, or storage indexes.
- Sequential independent calls. Use or bounded concurrency.
Promise.all - Unbounded concurrency. Batch large workloads to avoid rate limits; use about 5–10 concurrent requests unless docs or tests justify otherwise.
- Large resolver responses. Return only fields consumed by the UI.
函数内的每个API请求都会增加执行时长。检查以下点:
- N+1调用问题。将逐项获取替换为批量端点或返回所需字段的搜索API。
- 缺少、
fields、expand或limit约束。仅请求应用所需的数据。maxResults - 获取全部数据后再过滤。将过滤逻辑推送到JQL、CQL、REST查询参数或存储索引中。
- 顺序执行独立调用。使用或限制并发数。
Promise.all - 无界并发。对大型工作负载进行批量处理以避免速率限制;除非文档或测试另有说明,否则使用约5–10个并发请求。
- 过大的解析器响应。仅返回UI需要的字段。
Step 5: Optimize Storage
步骤5:优化存储
KVS and Custom Entity reads/writes are billed by data volume above free allowances; writes are much more expensive than reads.
Check for:
- Writes on every invocation even when values have not changed. Compare before writing or debounce writes.
- Very short cache TTLs for data that changes rarely. Prefer longer TTLs where staleness is acceptable.
- Storage reads/writes inside loops. Batch, restructure keys, or use Custom Entities queries.
- followed by in-memory filtering. Use
storage.query().getMany(),.index(...),.where(...), and cursor pagination..limit(...) - Large values where only a small subset is needed. Store normalized or trimmed values.
- Small, non-sensitive per-issue/page metadata stored in KVS. Consider Jira entity properties or Confluence content properties instead, noting visibility and 32 KB size constraints.
Do not move sensitive or confidential data to entity/content properties because they may be visible through product REST APIs.
超出免费额度后,KVS和自定义实体的读写按数据量计费;写入成本远高于读取成本。
检查以下场景:
- 每次调用都执行写入,即使值未发生变化。写入前进行比较或防抖处理。
- 针对很少变更的数据设置极短的缓存TTL。在可接受数据过期的情况下,优先使用更长的TTL。
- 循环内的存储读写操作。进行批量处理、重构键值或使用自定义实体查询。
- 执行后再进行内存过滤。使用
storage.query().getMany()、.index(...)、.where(...)和游标分页。.limit(...) - 存储大值但仅需其中一小部分。存储规范化或精简后的值。
- 在KVS中存储小型、非敏感的每个问题/页面元数据。可考虑使用Jira实体属性或Confluence内容属性,但需注意可见性和32 KB的大小限制。
不要将敏感或机密数据转移到实体/内容属性中,因为这些数据可能通过产品REST API被访问到。
Step 6: Optimize Logging
步骤6:优化日志
Find , , , , and structured logger calls.
console.logconsole.infoconsole.warnconsole.errorRecommended changes:
- Remove or gate debug logs in production hot paths.
- Never log full event payloads, API responses, storage values, secrets, tokens, personal data, or large JSON strings.
- Keep concise error logs and meaningful state changes.
- Add environment-variable gated debug logging only when useful, for example .
process.env.DEBUG_LOGGING === 'true'
查找、、、和结构化日志调用。
console.logconsole.infoconsole.warnconsole.error推荐更改:
- 移除或限制生产环境热点路径中的调试日志。
- 绝不要记录完整的事件负载、API响应、存储值、密钥、令牌、个人数据或大型JSON字符串。
- 保留简洁的错误日志和有意义的状态变更记录。
- 仅在有用时添加由环境变量控制的调试日志,例如。
process.env.DEBUG_LOGGING === 'true'
Step 7: Tune Function Memory
步骤7:调整函数内存
Inspect function entries in .
manifest.yml- The cost model is GB-seconds: .
(memoryMiB / 1024) × durationSeconds - Lower memory for lightweight resolvers only after considering performance and test coverage.
- Keep or increase memory for large payload processing if lower memory increases duration or causes failures.
- Prefer evidence: logs, profiling, benchmark results, or realistic local tests.
- If evidence is missing, recommend measurement rather than guessing aggressive memory reductions.
检查中的函数配置。
manifest.yml- 成本模型为GB秒数:。
(memoryMiB / 1024) × durationSeconds - 仅在考虑性能和测试覆盖率后,为轻量级解析器降低内存配置。
- 对于大负载处理任务,如果降低内存会增加执行时长或导致失败,则保留或增加内存配置。
- 优先依据证据:日志、性能分析、基准测试结果或真实的本地测试。
- 如果没有证据,建议先进行测量,而非盲目大幅降低内存。
Step 8: Evaluate Forge Remote Carefully
步骤8:谨慎评估Forge Remote
Forge Remote can remove Forge function execution for suitable workloads, but it shifts responsibility to externally operated infrastructure.
Only recommend Forge Remote when one or more are true:
- Long-running work exceeds standard Forge function limits.
- Compute-intensive processing dominates cost or runtime.
- The team already operates a secure backend that should own the logic.
- Storage/query needs genuinely exceed Forge platform capabilities.
Always mention trade-offs:
- The team must secure, scale, monitor, patch, and operate the remote backend.
- Remote architecture may affect Runs on Atlassian eligibility.
- The external infrastructure has its own costs and compliance obligations.
Forge Remote可将合适的工作负载移出Forge函数执行环境,但会将责任转移到外部运维的基础设施上。
仅在满足以下任一条件时推荐Forge Remote:
- 长时间运行的工作超出标准Forge函数限制。
- 计算密集型处理在成本或运行时占主导地位。
- 团队已运维一个安全的后端,且该后端应负责相关逻辑。
- 存储/查询需求确实超出Forge平台的能力。
务必提及权衡点:
- 团队必须负责远程后端的安全、扩容、监控、补丁和运维。
- 远程架构可能影响Runs on Atlassian的资格。
- 外部基础设施有其自身的成本和合规要求。
Safe Implementation Patterns
安全实施模式
When modifying code:
- Preserve behavior and authorization boundaries.
- Prefer small, reviewable commits worth of changes.
- Add or update tests when logic changes.
- Use existing project style and dependencies; do not add dependencies for simple utilities.
- Avoid sweeping rewrites unless the user explicitly asks.
- Validate with the narrowest relevant test/build command.
修改代码时:
- 保留原有行为和授权边界。
- 优先进行小范围、可评审的提交级更改。
- 逻辑变更时添加或更新测试。
- 使用项目现有的代码风格和依赖项;不要为简单工具添加新依赖。
- 除非用户明确要求,否则避免大范围重写。
- 使用最相关的窄范围测试/构建命令进行验证。
Finding Patterns Quickly
快速识别模式
Search for these patterns:
text
invoke(
useAction(
useEffect(
requestJira(
requestConfluence(
asApp().requestJira
asUser().requestJira
storage.get
storage.set
storage.query
console.log
console.info
scheduledTrigger
ignoreSelf
memoryMiB
Promise.all
for await
for (Interpret results carefully; a pattern is not automatically a problem.
搜索以下模式:
text
invoke(
useAction(
useEffect(
requestJira(
requestConfluence(
asApp().requestJira
asUser().requestJira
storage.get
storage.set
storage.query
console.log
console.info
scheduledTrigger
ignoreSelf
memoryMiB
Promise.all
for await
for (需谨慎解读结果;出现模式并不一定意味着存在问题。
Output Format
输出格式
For default audit-first requests, return the audit and end by offering to implement recommended changes:
markdown
undefined对于默认的先审计请求,返回审计结果并在结尾提出实施推荐更改的选项:
markdown
undefinedForge Cost Optimization Audit
Forge成本优化审计
Summary
摘要
- Overall opportunity: High | Medium | Low
- Highest-impact lever: <invocations | duration | storage | logs | memory | remote>
- Files inspected: <list>
- 整体优化空间:高 | 中 | 低
- 影响最大的优化点:<调用次数 | 执行时长 | 存储 | 日志 | 内存 | 远程服务>
- 检查的文件:<列表>
Prioritized Opportunities
优先级排序的优化机会
- [High] <title>
- Evidence: and observed pattern
<file:line> - Why it costs money: <cost driver>
- Recommended change: <specific fix>
- Safety notes: <authorization/data freshness/trade-offs>
- Evidence:
- [高] <标题>
- 证据:及观察到的模式
<file:line> - 成本影响原因:<成本驱动因素>
- 推荐更改:<具体修复方案>
- 安全说明:<授权/数据新鲜度/权衡点>
- 证据:
Quick Wins
快速优化项
- <low-risk change>
- <低风险更改>
Needs Measurement
需要测量的项
- <changes that require usage metrics or profiling>
- <需要使用指标或性能分析的更改>
Recommended Next Step
推荐下一步操作
Would you like me to implement the quick wins, implement selected high-impact changes, or collect usage measurements first?
For requests where the user explicitly asked for implementation, return:
```markdown您希望我实施快速优化项、实施选定的高影响更改,还是先收集使用数据?
对于用户明确要求实施的请求,返回:
```markdownForge Cost Optimization Complete
Forge成本优化完成
Changes Made
已做更改
- <file>: <change and cost driver reduced>
- <文件>: <更改内容及减少的成本驱动因素>
Validation
验证
- <commands run and results>
- <执行的命令及结果>
Expected Impact
预期影响
- <qualitative or measured impact>
- <定性或实测影响>
Follow-ups
后续建议
- <optional deeper optimizations or metrics to collect>
undefined- <可选的深度优化或需收集的指标>
undefinedAnti-Patterns to Avoid
需避免的反模式
- Do not move privileged operations to the frontend.
asApp() - Do not expose secrets, app credentials, or admin-only data in browser code.
- Do not use entity properties for sensitive data.
- Do not remove logs needed for production incident diagnosis; reduce verbosity instead.
- Do not increase cache TTL beyond acceptable product freshness requirements.
- Do not recommend Forge Remote as a default; it is an architectural trade-off, not a simple cost switch.
- Do not claim exact savings without actual usage metrics.
- 不要将特权操作转移到前端。
asApp() - 不要在浏览器代码中暴露密钥、应用凭证或仅管理员可见的数据。
- 不要使用实体属性存储敏感数据。
- 不要移除生产环境故障排查所需的日志;应减少日志冗余。
- 不要将缓存TTL设置超出可接受的产品数据新鲜度要求。
- 不要将Forge Remote作为默认选项;它是一种架构权衡,而非简单的成本开关。
- 不要在没有实际使用指标的情况下声称确切的节省金额。