diff --git a/assets/css/case-studies.scss b/assets/css/case-studies.scss index 31b64f27..c21178d6 100644 --- a/assets/css/case-studies.scss +++ b/assets/css/case-studies.scss @@ -1534,6 +1534,13 @@ html:has(.cs-sticky-nav) { strong { color: #fff; } + h3, + h4 { + color: #fff; + } + h3 { + border-top-color: rgba(255, 255, 255, 0.14); + } ul > li::before { @include csi-grad-solid; } @@ -1580,12 +1587,28 @@ html:has(.cs-sticky-nav) { } } + // ---- Default LEFT alignment — the content renders as a CENTERED article + // column (text stays left-aligned, the column centres in the band) so + // wide viewports don't leave a dead right half. Only csi-section + // emits --left (csi-split carries its own grid and no align class), + // and every MarketSpark / Power Digital section is --center, so this + // only shapes the consolidated narrative bands (Cursor). + &--left { + .csi-section__head, + .csi-prose { + max-width: 860px; + margin-left: auto; + margin-right: auto; + } + } + // ---- COMPACT band — applied automatically to any section containing a // csi-list or csi-questions (no opt-in arg): same content, less // vertical real estate. Tighter padding, smaller head, denser prose - // and pull quote. - &:has(.csi-list), - &:has(.csi-questions) { + // and pull quote. `roomy="true"` (csi-section--roomy) opts a long + // consolidated band back out — its bulk is narrative, not the list. + &:has(.csi-list):not(.csi-section--roomy), + &:has(.csi-questions):not(.csi-section--roomy) { padding: 2.5rem 0; @media (max-width: 991px) { padding: 2.1rem 0; @@ -1821,6 +1844,46 @@ html:has(.cs-sticky-nav) { } } + // In-card subsection heads + inline media — consolidated bands (Cursor) + // carry several source sections inside ONE band: markdown ### become the + // in-card chapter heads (hairline divider between chapters), markdown + // images the inline charts, and csi-figure drops a CSS-drawn figure into + // the prose flow. Pine faces recolour the heads inside the --pine block. + .csi-prose h3, + .csi-prose h4 { + color: $csi-ink; + font-weight: 800; + line-height: 1.3; + } + .csi-prose h3 { + font-size: clamp(1.35rem, 2.2vw, 1.7rem); + margin: 2.8rem 0 1rem; + padding-top: 2.4rem; + border-top: 1px solid $csi-line; + } + .csi-prose > h3:first-child { + margin-top: 0.4rem; + padding-top: 0; + border-top: 0; + } + .csi-prose h4 { + font-size: 1.18rem; + margin: 2.2rem 0 0.8rem; + } + .csi-prose img { + display: block; + width: 100%; + height: auto; + border-radius: 14px; + margin: 1.7rem auto; + box-shadow: 0 18px 44px -28px rgba(8, 30, 30, 0.45); + } + .csi-figure { + display: flex; + justify-content: center; + margin: 2.2rem auto; + } + // --------------------------------------------------------------------------- // SPLIT — text + visual side by side, alternating with --flip // --------------------------------------------------------------------------- @@ -2294,6 +2357,81 @@ html:has(.cs-sticky-nav) { // NOTE: the ledger stays a WHITE card on dark faces too (no pine override) // — the hard numbers read best on white, and the card pops off the band. + // --------------------------------------------------------------------------- + // TABLE — csi-table: a compact metric table for numbers that outgrow the + // two-column csi-compare ledger (an extra "Change"/"Improvement" delta + // column). Same rule as the ledger: it stays a WHITE card on dark faces. + // The delta column (`accent="true"`) carries the brand gradient — its + // classes are registered in the print gradient-fallback list. + // --------------------------------------------------------------------------- + .csi-table { + max-width: 980px; + margin: 2.2rem auto 0; + text-align: left; + + &__card { + background: #fff; + border: 1px solid $csi-line; + border-radius: 16px; + box-shadow: 0 16px 36px -26px rgba(8, 30, 30, 0.32); + overflow: hidden; + } + &__title { + padding: 1rem 1.4rem 0.9rem; + font-size: 1.02rem; + font-weight: 800; + color: $csi-ink; + border-bottom: 1px solid $csi-line; + } + &__scroll { + overflow-x: auto; + } + table { + width: 100%; + min-width: 620px; + border-collapse: collapse; + margin: 0; + font-size: 0.95rem; + } + thead { + // strip tint lives on the row, NOT the th — a bg on the th would + // out-specify the gradient mixin on th.csi-table__delta-head and leave + // its clipped text invisible (flat bg + transparent fill) + background: rgba(20, 48, 47, 0.03); + } + th { + padding: 0.8rem 1.4rem; + font-size: 0.7rem; + font-weight: 800; + letter-spacing: 0.14em; + text-transform: uppercase; + text-align: left; + color: #8aa09f; + border-bottom: 1px solid $csi-line; + white-space: nowrap; + } + td { + padding: 0.95rem 1.4rem; + color: #7d9291; + line-height: 1.45; + vertical-align: top; + } + td:first-child { + font-weight: 700; + color: $csi-ink; + } + tbody tr + tr td { + border-top: 1px solid $csi-line; + } + &__delta-head { + @include csi-grad-light; + } + &__delta { + font-weight: 800; + @include csi-grad-light; + } + } + // --------------------------------------------------------------------------- // FIGURE — TERRALITH (csi-split figure="terralith"). CSS-drawn monolith → // isolated stacks: no image asset, inherits page fonts, recolours per face, @@ -3075,6 +3213,8 @@ html:has(.cs-sticky-nav) { .csi-questions__outro-main strong, .csi-compare__col--after, .csi-compare__after, + .csi-table__delta-head, + .csi-table__delta, .cs-hero__title .text-gradient { background: none !important; -webkit-background-clip: border-box !important; @@ -3117,6 +3257,8 @@ html:has(.cs-sticky-nav) { .csi-testimonial, .csi-impact__card, .csi-compare__row, + .csi-table__card, + .csi-prose img, .csi-fig-terralith__mono, .csi-fig-terralith__stack, .csi-timeline, diff --git a/content/case-studies/cursor.md b/content/case-studies/cursor.md new file mode 100644 index 00000000..0f5f2482 --- /dev/null +++ b/content/case-studies/cursor.md @@ -0,0 +1,325 @@ +--- +title: "75% Faster Plans, 2x Daily Applies: How Cursor Rebuilt Its Terraform Workflow with Masterpoint" +weight: 1 +description: "At Masterpoint, we focused on Terraform and IaC improvements so our client Cursor could focus on making their users extraordinarily productive." + +layout: immersive + +# Hero +eyebrow: "CASE STUDY SUCCESS STORY" +client: "Cursor" +client_logo: /img/case-studies/cursor/cursor-lockup-white.svg +client_logo_height: 30px +hero_title: "75% Faster Plans, 2x Daily Applies: How Cursor Rebuilt Its Terraform Workflow with Masterpoint" +hero_aside_image: /img/case-studies/cursor/deploy-frequency-growth.png +hero_aside_alt: "Line chart of Cursor's weekly infrastructure PRs climbing from 194 in October 2025 to 500+ by May 2026" + +# At-a-glance stat strip (appears under hero) +stat_bar: + - value: "~8 min → ~2 min" + label: "median plan time (production)" + - value: "~194 → 500+" + label: "deployment PRs / week (+157%)" + - value: "54 → 5" + label: "median resources affected (91% smaller blast radius)" + - value: "100+" + label: "narrow, independent root modules" + +# Preview / OG +preview_image: /img/case-studies/cursor/plan-time-before-after.png +og_img: /img/case-studies/cursor/plan-time-before-after.png + +sitemap: + priority: 0 + +callout: >- +
If your team is hitting Terraform + ceilings like:
+Masterpoint can help. We've done this work at scale, for engineering + organizations that can't afford to slow down. + Get in touch →
+--- + +{{< csi-testimonial tldr="true" variant="pine" >}} +At Masterpoint, we focused on **Terraform and IaC improvements** so our client Cursor could focus on making their users **extraordinarily productive**. +{{< /csi-testimonial >}} + +{{< csi-section eyebrow="At a Glance" title="Key Value Delivered" variant="light" align="center" >}} +{{< csi-impact cols="2" >}} +icon: fa-gauge-high +title: Dramatically faster plans +body: Plan time dropped significantly. Originally plan time had spikes of 10+ minutes; after our work, plan time was roughly 2 minutes. +--- +icon: fa-rocket +title: Improved delivery speed +body: Engineers shipped 157% more PRs per week after the engagement, and have increased shipping cadence since. +--- +icon: fa-rotate +title: More frequent, safer deploys +body: Weekly infrastructure PRs grew from 194 to 500+, and fewer plans were abandoned as the apply-to-plan ratio improved from 55% to 64%. +--- +icon: fa-crosshairs +title: Safer, more contained changes +body: The median Terraform run now touches 5 resources instead of 54 — a 91% smaller blast radius, so engineers can reason about exactly what a change will affect before applying it. +{{< /csi-impact >}} +{{< /csi-section >}} + +{{< csi-section id="the-challenge" eyebrow="The Challenge" title="The Problem: Infrastructure That Couldn’t Keep Up" variant="pine" >}} +By late 2025, Cursor's Terraform setup had become one of the biggest friction points in the engineering org. The company behind the Cursor IDE experienced issues familiar to fast-growing startups: infrastructure code written quickly, then scaled by copy-pasta rather than through careful design. + +Those early Terraform patterns were replicated at machine speed as engineers dogfooded Cursor. They were copied and instantiated hundreds of times without the architectural guardrails needed to keep the system manageable. The result was a classic [**terralith**](/blog/terralith-monolithic-terraform-architecture/): critical infrastructure was managed as a single monolithic production workspace with over 7,000 resources in one state file. + +{{< csi-figure name="cursor/terralith" >}} + +And because that workspace was so large, it was too slow. + +{{< cs-pullquote name="Travis McPeak" title="Security Lead" company="Cursor" >}} +We had one giant workspace that took way too long to plan. It was killing us. +{{< /cs-pullquote >}} + +But the problem wasn't just the lack of speed. It was a lack of engineering confidence in the IaC system. Issues included: + +- The AWS console was used to make changes during incidents and these fixes were never rolled into TF, and so were later inadvertently reverted. +- Managing ECS deployments through Terraform caused constant drift in the production terralith, flooding PR diffs with hundreds of unrelated changes. + +Over time, the team stopped trusting the system, let alone reading the diffs. + +{{< cs-pullquote name="Travis McPeak" title="Security Lead" company="Cursor" >}} +We would have engineers click apply on prod workspaces that had 120 ECS service changes. The ECS services would change all the time because of drift, so the team became desensitized to large Terraform plan changes. +{{< /cs-pullquote >}} + +This confusion caused downtime, such as a network firewall change that caused a 10 minute outage. + +The existing platform, Terraform Cloud, introduced some friction too: + +- Workspace management relied on manual [ClickOps](/blog/terraform-opentofu-terminology-breakdown/#clickops) configuration for each new workspace. +- The SSO experience was inconsistent. +- TFC's resource-under-management (RUM) pricing model made it daunting to scale. +{{< /csi-section >}} + +{{< csi-section id="the-work" eyebrow="The Engagement" title="What Masterpoint Did" variant="light" roomy="true" >}} +Masterpoint came in for a systematic overhaul, working across the architecture, the platform, and the developer workflow. + +{{< csi-timeline marker="50" marker_label="February 2026 · migration done" >}} +label: Terraform Cloud + Terraform +note: workspaces migrate off in phases +start: 0 +end: 50 +fade: out +--- +label: Spacelift + OpenTofu +note: pilot stack first, then bulk migration +start: 22 +end: 100 +fade: in +{{< /csi-timeline >}} + +### November 2025 - Audit and High Leverage Fixes + +The engagement opened with an [audit](/services/audit/) of Cursor's infrastructure: + +- cloud environments +- IaC setup +- CI/CD pipelines +- networking +- observability + +Within a week, Masterpoint delivered an audit report, a best practices checklist, and a security scan. The findings included IAM duplication accounted for 70% of the production TF state and noisy plan diffs caused engineer fatigue. + +The audit phase targeted the highest-leverage fixes first: IAM resource deduplication, workspace trigger and path filter corrections so plans only ran when relevant code changed, and initial provider alias splits to begin isolating staging and ML infrastructure from the main production workspace. + +By November 25th, the IAM deduplication fixes had landed. + +{{< csi-table head="Metric | Before | After | Change" accent="true" >}} +row: Resource Count | 8,480 | 4,593 | 45.8% reduction (3,887 resources removed) +{{< /csi-table >}} + +The number of production resources dropped from 8,480 to 4,593, a 46% reduction. Mean plan time fell from 8.1 minutes to 4.9 minutes, a 39% improvement. The P95 plan time improved even more. + +{{< csi-table head="Metric | Before (Nov 20–24) | After (Nov 25–Dec 8) | Improvement" accent="true" >}} +row: Mean | 488.8s (8.1 min) | 296.6s (4.9 min) | 39.3% faster +row: P50 (Median) | 423s (7.1 min) | 272s (4.5 min) | 35.7% faster +row: P95 | 749s (12.5 min) | 414s (6.9 min) | 44.7% faster +row: Sample Size | 38 runs | 184 runs | n/a +{{< /csi-table >}} + +This was accomplished without touching the workspace structure, but the systems could still be improved. + +### December 2025 - Spacelift Migration Begins + +With the first phase complete, Masterpoint turned to the platform. + +As mentioned above, TFC's ClickOps workspace management, SSO troubles, and resource-under-management pricing were all inhibiting Cursor's velocity and growth. + +Masterpoint recommended a move to [Spacelift](/services/spacelift/) to address these issues. + +The team kicked off the Spacelift migration in mid-December, starting with the groundwork: + +- naming and tagging standards +- AWS multi-account IAM role architecture +- Okta SSO configuration + +Rather than migrating everything at once, a low-risk pilot Spacelift stack (the equivalent of a TFC workspace) was used to validate the approach. The end-to-end fully automated pilot project was completed within days. + +Masterpoint also began evaluating a full migration from the Terraform runtime to [OpenTofu](https://opentofu.org/). + +### January to February 2026 - Bulk Migration + +With a plan covering a migration of dozens of TFC workspaces across four phases, the team worked systematically. By late January, the bulk of workspaces had been migrated to Spacelift stacks with no operational downtime for the Cursor engineering organization. + +By February, the migration was done. All workspaces had been moved from TFC to Spacelift and the runtime was converted from Terraform to OpenTofu. Migrating to OpenTofu freed Cursor from licensing constraints and unlocked capabilities unavailable or paywalled in Terraform, such as state encryption, OpenTelemetry support, and provider iteration. + +As part of the final migration work, the production workspace was reduced by splitting out various provider-aliased resources into dedicated stacks, continuing the decomposition work that had started with IAM deduplication in November. + +### February to May 2026 - AI Agent Guardrails And Additional Improvements + +After the migration was completed, Masterpoint continued to improved system usability and speed by: + +- restructuring Route53 DNS API requests into optimized, dedicated TF modules to address AWS's strict 5 requests/second limit +- continuing to break up large state files into narrower root modules, allowing for faster plans (further reducing critical infrastructure plans from roughly 5 minutes to under 2 minutes) and decreased blast radius +- implementing child module versioning with OCI registries to enable staged rollouts and safer change control of critical TF resources +- resolving the ECS drift issue by using the ["Task Definition Template Pattern"](https://newsletter.masterpoint.io/p/deploying-your-apps-into-ecs) +- implementing OpenTofu's [OTel tracing](https://opentofu.org/docs/internals/tracing/) to set up the Cursor team for longterm visibility into their IaC throughput + +Because Cursor's engineering team uses Cursor to write Terraform, Masterpoint embedded architectural knowledge directly into the codebase as AI agent skills and rules. + +This AI context encodes the decisions that AI models cannot anticipate on their own: + +{{< csi-list >}} +icon: fa-sitemap +title: when to create a new root module vs. extend an existing one +--- +icon: fa-crosshairs +title: how to scope blast radius in a root module +--- +icon: fa-cubes +title: how to break up a high blast radius monolithic root module +--- +icon: fa-database +title: data source patterns and optimizations +--- +icon: fa-box-open +title: how to use OCI-sourced child modules +--- +icon: fa-shield-halved +title: security practices, such as TF module SHA pinning +--- +icon: fa-magnifying-glass-chart +title: debugging performance bottlenecks, through methods such as logging and OpenTelemetry traces +{{< /csi-list >}} + +{{< cs-pullquote name="Ravi Rahman" title="Software Engineer" company="Cursor" >}} +The AI agent skills and rules help us build our IaC correctly while at the same time moving faster. +{{< /cs-pullquote >}} + +Every IaC optimization Masterpoint delivered was paired with instructions to prevent anti-patterns from being reintroduced. +{{< /csi-section >}} + +{{< csi-section id="the-results" accent="true" title="The Results" variant="pine" roomy="true" >}} +### What Cursor’s Infrastructure as Code Manages + +The Cursor infrastructure today includes: + +{{< csi-list >}} +icon: fa-server +title: hundreds of ECS services with tens of thousands of live running tasks +--- +icon: fa-microchip +title: thousands of EC2 instances +--- +icon: fa-layer-group +title: dozens of Redis clusters +--- +icon: fa-database +title: a few dozen databases +--- +icon: fa-network-wired +title: in the triple digits of ALB and NLB load balancers +{{< /csi-list >}} + +In all 40k+ Terraform resources are managed using the new platform. All of this exists in 100+ narrow, independent root modules, with [OpenTofu](https://opentofu.org/), on [Spacelift](https://spacelift.io/), using Okta SSO, stored in S3-backed state, and paired with AI agent rules to keep the architecture clean as the codebase grows. + +### Numbers That Matter + +{{< csi-compare >}} +label: Median plan time (production) +before: ~8 min +after: ~2 min +--- +label: Deployment PRs / week +before: ~194 +after: 500+ (+157%) +--- +label: Median resources affected +before: 54 +after: 5 (91% reduction in blast radius) +{{< /csi-compare >}} + +### Plan time went from 10+ minutes to 2 minutes + + + +The production workspace plan time dropped from over 10+ minutes, with spikes to 15 minutes, during the November baseline to around 2 minutes by mid 2026. + +This is an improvement of roughly 75% from where the engagement started, and more than 80% from the pre-engagement peak. + +### Deployment frequency increased + + + +Weekly merged PRs against infrastructure as code went from approximately 194 per week to over 500 a week, a 157% increase. They've only accelerated since then. + +### The productivity lift was significant + +This gain wasn't from growing the engineering organization: a controlled same-cohort analysis of 34 engineers active both before and after the Masterpoint engagement found that PR throughput grew by 121%. + +{{< csi-table head="Metric | Pre-engagement | End of Engagement | Change" accent="true" >}} +row: Cohort throughput | 63 PRs/wk | 140 PRs/wk | +121% +row: Per-active-week cadence | 5.37 PRs/author/wk | 9.19 PRs/author/wk | +71% +{{< /csi-table >}} + +### Infrastructure became democratized + + + +Looking beyond the controlled same-cohort set of engineers, 89% of all engineers who work with infrastructure now ship Terraform PRs each month. + +Previously, workspace creation required manual ClickOps and admin access. Today, engineers create and manage their own stacks. The number of separately managed modules went from 26 to 100+. Engineers are now creating their own product/domain scoped infrastructure instead of jumbling it in the primary monolithic workspace. +{{< /csi-section >}} + +{{< csi-section accent="true" title="What Changed for the Team" variant="light" >}} +### Engineers know what an IaC Terraform change will touch + +Before the engagement, engineers couldn't predict what a change would actually touch in a workspace. A database might live in a workspace named for networking infrastructure, so even finding where something was managed required tribal knowledge. Dependencies between workspaces were just as opaque: touching one piece of infrastructure could ripple into systems that had nothing to do with the change — or surface long-standing drift that did. Plans intended for one system would silently queue in unrelated workspaces, waiting for the next person to find them with no context on where they came from or whether they were safe to apply. + +{{< cs-pullquote name="Ravi Rahman" title="Software Engineer" company="Cursor" >}} +The Terraform experience has gotten way better. For the first time since I've been here, we just merge and apply. If something's wrong, the system lets us know. It's fast and moves at the speed we need. +{{< /cs-pullquote >}} + +With smaller, focused stacks, plans are scoped to the change at hand. The median Terraform run now touches just 5 resources instead of 54 — a 91% smaller blast radius — so engineers know precisely what a plan will affect before they run it. + + + +### Architectural flexibility enables the business and product delivery + +Before the engagement, the terralith made architectural changes expensive and risky. Touching one piece of infrastructure meant disrupting unconnected components. + +With narrow stacks owning a focused piece of infrastructure, the Cursor engineering team can more easily modify their architecture. + +New services, providers, and cloud targets can be added as their own stacks, which is a foundation that directly enables expansion into multi-cloud infrastructure as Cursor continues to scale. + +### Cursor’s agents are set up for future success + +Since Cursor's engineers rely on Cursor to write their own Terraform, Masterpoint embedded the new architecture into AI agent rules and skills that sit directly within the codebase. + +These rules capture the patterns and decisions that LLMs can't figure out on their own, setting the team up to consistently ship high-quality infrastructure code, now and as the system evolves. +{{< /csi-section >}} + +{{< csi-testimonial name="Travis McPeak" title="Security Lead" company="Cursor" variant="pine" image="/img/bg_our_word.jpg" >}} +Masterpoint didn't just fix our IaC. They gave our entire engineering org the confidence to move fast. We went from a system people were afraid to touch Terraform to where nearly every engineer is quickly and assuredly shipping infrastructure changes every week. +{{< /csi-testimonial >}} diff --git a/docs/case-studies.md b/docs/case-studies.md index 54402cc6..28113eb8 100644 --- a/docs/case-studies.md +++ b/docs/case-studies.md @@ -24,11 +24,11 @@ July 2026 once Power Digital, its last user, was rebuilt on immersive.) | Layout | Template | Used by | Body class | Style prefix | | ------------- | ------------------------------------- | ------------------------------------------------------- | ----------------------------------- | ----------------------- | | **Modern** | `layouts/case-studies/single.html` | Default for any case study without a `layout:` override | `case-study-modern` | `.case-study-modern` | -| **Immersive** | `layouts/case-studies/immersive.html` | MarketSpark, Power Digital (opt-in via `layout: immersive`) | `case-study-modern case-study-immersive` | `.case-study-immersive` | +| **Immersive** | `layouts/case-studies/immersive.html` | MarketSpark, Power Digital, Cursor (opt-in via `layout: immersive`) | `case-study-modern case-study-immersive` | `.case-study-immersive` | Routing is via Hugo's `layout:` front matter param. A case study that does -**not** specify `layout:` uses `single.html` (the modern layout). MarketSpark -and Power Digital opt into immersive with `layout: immersive`. +**not** specify `layout:` uses `single.html` (the modern layout). MarketSpark, +Power Digital, and Cursor opt into immersive with `layout: immersive`. The **modern** layout was designed from scratch and is the default for new case studies. The @@ -159,6 +159,34 @@ All shortcodes are in `layouts/shortcodes/cs-*.html` and styled under - **CSS-drawn figures beat images for diagrams** (`csi-split figure="…"` → `figures/| {{ trim $h " " | safeHTML }} | + {{- end }} +
|---|
| {{ trim $c " " | $.Page.RenderString (dict "display" "inline") }} | + {{- end }} +