🚀 Full-Stack Web Performance Optimization: Frontend, Backend, and Database Strategies

2025/07/14

Introduction

In this post, I’ll walk you through the web optimization work I did on one of my recent projects this year. As a full-stack developer, I’ll focus mainly on code-level optimizations from a developer’s perspective — covering both frontend and backend. While server infrastructure isn’t the main focus, I’ll also highlight a few key server-side improvements worth noting.

For context, the project is called SPMB Jawa Barat (previously known as PPDB Jawa Barat). It’s a web-based registration system used by junior high school students in the West Java region to apply to senior high schools (SMA) or vocational schools (SMK).

According to Google Analytics, the website received around 1.5 million visitors between June 1st and July 11th. The official registration was split into two phases: the first from June 10th to June 17th, and the second from June 24th to July 1st. As a result, you’ll notice significant traffic spikes during those periods on the Analytics graph. Outside of those dates, the site still saw activity from users preparing for registration, taking offline exams, and from schools verifying applicant data.

According to our database, there are 1.189.900 junior high school student records, and out of those, 570.874 students successfully completed their registration through the SPMB system.

Google Analytics SPMB Jawa Barat 2025

Tech Stack

📦 InfraDocker, Kubernetes, Nginx, Varnish, Cloudflare CDN, MinIO
⚙️ BackendGolang, go-chi, PostgreSQL with Replication, PGBouncer, Redis
🧠 FrontendVue.js, TailwindCSS, Vite

Server Optimization

I'm not an expert in this area, but I’ll do my best to explain what I’ve learned — this part of the system was actually handled by a friend, and I asked as many questions as I could to understand it 😁.

If you're a DevOps engineer or software developer, you're probably already familiar with Docker, Kubernetes, and Nginx. What stood out to me — and was completely new — were Varnish and Cloudflare. I also encountered MinIO for the first time, which turned out to be quite straightforward — it's essentially a self-hosted alternative to Amazon S3.

Varnish is used to cache API responses at the server level. However, not all responses are cacheable, so we mainly used Varnish to cache static or rarely changing data.

As for Cloudflare, we utilized its CDN features to serve the frontend assets. This helps reduce server load by delivering static files from the nearest edge location, so users don’t hit our servers directly every time they visit the site.

Backend Optimization

For the backend, we chose Golang for this web app because it offers significantly better performance and lower memory usage compared to our previous stack — Express.js, which we used in PPDB Jawa Barat (2020–2023).

We use PostgreSQL as our main database, with four read replicas distributed across backend services to handle high read traffic. To manage database connections efficiently, we also implemented PgBouncer for connection pooling.

For caching, we use Redis at the backend level. Unlike Varnish (which caches mostly static API responses at the edge), Redis helps us cache both dynamic data — like registrant details — and static data that’s accessed frequently, such as web configuration settings. Redis caching isn’t limited to API responses; we also use it to offload frequently queried metadata and improve response times across the app.

Frontend Optimization

You might wonder — why didn’t we choose React, especially when it’s everywhere? For this project, we went with Vue.js because it offers comparable (or slightly better) performance with a faster and more efficient development experience — especially helpful under a tight deadline.

Another common question: why not use SSR (Server-Side Rendering)? We've been using Vue (without Nuxt.js or SSR) since 2019. Back then, we had limited server capacity, and Vue as an SPA framework was lightweight and reliable. That setup has served us well, so we’ve continued with it ever since.

We also implemented frontend-level caching for backend configuration data. When a user requests config data, we first check localStorage. If it's available and not expired, we use it; otherwise, we fetch it from the backend API. This helps reduce unnecessary network requests and speeds up load time.

For the build tool, we used Vite — now the standard for Vue 3 projects. Personally, I really love the Vue + Vite combo. Our CI/CD pipeline takes just ~50 seconds to complete a deployment. In contrast, our old Vue + Webpack setup took around 3 minutes, and some of my SSR projects (like those built with Nuxt.js or Next.js) can take 5–15 minutes — although those aren’t under my direct control, so I can’t fully verify the CI/CD optimizations there.

Obstacles

The registration process ran smoothly overall thanks to our chosen tech stack — though we did face issues during the first and second days of registration. The main problem occurred with the MinIO service, which experienced failures when attempting to write data. Interestingly, the issue wasn’t caused by our code, but rather by unusually slow internet performance on the server’s ISP during the first day.

As developers, there wasn’t much we could do about the network conditions themselves. However, we responded by optimizing the logic around the storage service to reduce resource usage and minimize the impact during those critical periods.

Final Thoughts

Optimizing a high-traffic web application like SPMB Jawa Barat required careful consideration at every level — from frontend efficiency to backend performance and database scalability. While no system is perfect, and some challenges (like network issues) were out of our control, choosing the right tools and making intentional design decisions helped us handle millions of users with confidence.

Every layer — whether it's using Vue + Vite for fast frontend builds, Golang and PostgreSQL for high-performance backend processing, or Redis and Varnish for caching — played a critical role in the overall success of the project.

I’m still learning, and this project gave me the opportunity to dive deeper into areas like infrastructure, caching strategies, and performance tuning. Hopefully, sharing this experience gives you some insight or ideas for your own projects.

Thanks for reading — feel free to reach out if you want to discuss or ask about any part of this post!