How do you build and deploy Bitbucket Forge apps, and what are the architectural trade-offs compared to Connect apps?
Quick Answer
Bitbucket Forge apps are serverless extensions built with JavaScript/TypeScript that run on Atlassian's infrastructure, eliminating hosting and operations overhead. They trade deployment control and execution flexibility for simplified development and automatic scaling. Connect apps offer full control but require self-hosted infrastructure, HTTPS endpoints, and operational responsibility.
Detailed Answer
Think of the Connect vs Forge decision like choosing between renting a food truck (Connect) and having a ghost kitchen (Forge). The food truck (Connect) goes wherever you want, serves whatever menu you design, and you maintain the vehicle yourself. The ghost kitchen (Forge) handles the kitchen, delivery, and staffing, but you must cook within the kitchen's constraints (limited equipment, standardized processes). Both serve food to the same customers (Bitbucket users), but the operational model is fundamentally different.
Bitbucket Forge apps are built using the Atlassian Forge platform, which provides a serverless runtime for extending Atlassian products. You write functions in JavaScript or TypeScript using the Forge SDK, define your app's modules in a manifest.yml file, and deploy with the 'forge deploy' CLI command. Atlassian hosts and executes your code on their infrastructure (AWS Lambda under the hood). Forge supports several Bitbucket modules: merge checks, webhooks, repository hooks, custom UI panels, and triggers. The development workflow uses 'forge tunnel' for local development, which proxies requests from Atlassian's infrastructure to your local machine for real-time debugging.
Architecturally, Connect apps are traditional web applications that Bitbucket communicates with via HTTP webhooks and iframe embedding. The app developer hosts the application (on AWS, GCP, Heroku, or on-premise), manages SSL certificates, handles scaling, and implements security (JWT verification for incoming webhooks). Connect apps have full network access and can call any external API, store data in any database, and run long-running processes. They are limited only by HTTP timeout constraints (10-30 seconds depending on the module). Connect apps use the atlassian-connect.json descriptor to register their capabilities with Bitbucket.
Forge apps have several architectural trade-offs. The advantages are significant: zero infrastructure management, automatic scaling, built-in authentication (no JWT verification needed), and Forge Storage (a simple key-value store for app data). The constraints are equally significant: execution time limit of 25 seconds per invocation, limited runtime environment (Node.js only, specific version), restricted network access (egress must be configured explicitly), 128 MB memory limit per function, and no persistent filesystem. Forge apps cannot call internal APIs behind a firewall without Forge Remotes (a tunneling mechanism), which adds complexity. Data stored in Forge Storage is scoped to the app and has size limits.
In production, the choice between Connect and Forge depends on the app's complexity and the organization's operational capacity. Forge is ideal for lightweight extensions: merge checks that query Jira, PR decorators that add status badges, webhook handlers that trigger external systems. Connect is necessary for complex integrations: apps that need persistent WebSocket connections, large data processing, integration with on-premise systems, or custom UI experiences beyond Forge's UI kit. Some organizations start with Forge for rapid prototyping and migrate to Connect when they hit Forge's limitations. The hybrid approach uses Forge for the Bitbucket-facing modules (merge checks, UI panels) and delegates complex processing to an external service via HTTP calls from the Forge function.
A gotcha that surprises Forge developers: Forge apps run in a sandboxed environment where standard Node.js modules that interact with the filesystem, spawn child processes, or open raw sockets are unavailable. Libraries that depend on native C++ bindings (like bcrypt or sharp) will not work. Another trap is cold start latency: Forge functions that have not been invoked recently may take 1-3 seconds to cold-start, which can affect the user experience for merge checks that need to respond quickly. Connect apps avoid cold starts by running continuously but pay for that with hosting costs.